Почему мои флажки не обновляются с помощью Redux? - PullRequest
0 голосов
/ 05 августа 2020

Я работаю над мобильным приложением React-Native, использующим Redux для управления состоянием. У меня есть фильтр для управления отображаемыми данными.

Я использую Redux для управления всеми данными в фильтрах.

Это довольно просто: я нажимаю на флажок, он щелкается. Я снова нажимаю на флажок (угадайте, что), он снимается. Когда есть поле со значением «allInclusive», все флажки сняты, кроме «allInclusive».

Вот код редуктора и код элемента Checkbox.

var comparators = {...state.comparators};
      if (!comparators[action.payload.comparator]) {
        comparators[action.payload.comparator] = {};
        comparators[action.payload.comparator][action.payload.name] = [action.payload.value];
      } else {
        if (!comparators[action.payload.comparator][action.payload.name]) {
          comparators[action.payload.comparator][action.payload.name] = [action.payload.value];
        } else {
          if (comparators[action.payload.comparator][action.payload.name].includes(action.payload.value)) {
            comparators[action.payload.comparator][action.payload.name] = comparators[action.payload.comparator][action.payload.name].filter(value => value !== action.payload.value);
          } else {
            comparators[action.payload.comparator][action.payload.name].push(action.payload.value);
          }
        }
      }
      return Object.assign({}, state, {
        comparators,
      });
import React, {Component} from 'react';
import {View, StyleSheet} from 'react-native';
import colors from '../res/colors/index';
import {CheckBox} from 'react-native-elements';
import PropTypes from 'prop-types';
import {Text} from '.';
import {style} from 'd3';
import i18n from '../i18n/i18n';
import {connect} from 'react-redux';
import * as actions from '../actions';

export class ComparatorCheckboxesContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {checked: false};
  }

  checked(value) {
    if (this.props.filter.includes('allInclusive')) {
      return value === 'allInclusive';
    }
    alert(JSON.stringify(this.props.filter));
    return this.props.filter.includes(value);
  }

  render() {
    return (
      <View style={styles.checkboxesContainer}>
        <Text style={styles.checkboxesTitle}>
          {this.props.title + JSON.stringify(this.props.filter)}
        </Text>
        {this.props.options.map(option => (
          <CheckBox
            checkedIcon="check-square-o"
            uncheckedIcon="square-o"
            checkedColor={colors.principal}
            checked={this.checked(option.value)}
            onPress={() =>
              this.props.checkboxFilterChange(
                this.props.type,
                this.props.name,
                option.value,
              )
            }
            title={i18n.t(option.title)}
            containerStyle={styles.containerStyle}
            textStyle={style.textStyle}
            fontStyle={style.textStyle}
          />
        ))}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  checkboxesContainer: {
    width: '100%',
    marginLeft: 'auto',
    marginRight: 'auto',
    marginTop: 14,
  },
  checkboxesTitle: {
    fontSize: 10,
    color: colors.darkGray,
  },
  checkboxLine: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'flex-start',
    alignItems: 'center',
  },
  checkboxLineText: {
    fontSize: 16,
    color: colors.darkGray,
  },
  containerStyle: {
    backgroundColor: 'transparent',
    borderWidth: 0,
    marginBottom: 0,
    marginTop: 0,
    padding: 10,
  },
  textStyle: {
    marginLeft: 2,
    color: colors.darkGray,
  },
});

const mapStateToProps = ({comparators}, ownProps) => {
  if (comparators.comparators[ownProps.type] && comparators.comparators[ownProps.type][ownProps.name]) {
    return {
      filter: comparators.comparators[ownProps.type][ownProps.name],
    };
  } else {
    return {
      filter: [],
    }
  }
};

export default connect(
  mapStateToProps,
  actions,
)(ComparatorCheckboxesContainer);

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Вот редюсер, переписанный как неизменяемый:

 const { comparators } = state;
  const { comparator, name, value } = action.payload;

  if (!comparators[comparator]) {
    return {
      ...state,
      comparators: {
        [comparator]: {
          [name]: value
        }
      }
    };
  } else {
    return !comparators[comparator][name]
      ? {
          ...state,
          comparators: {
            [comparator]: {
              [name]: value
            }
          }
        }
      : comparators[comparator][name].includes([value])
      ? {
          ...state,
          comparators: {
            [name]: comparators[comparator][name].filter(val2 => val2 !== value)
          }
        }
      : {
          ...state,
          comparators: {
            [comparator]: {
              [name]: [...comparators.comparator.name, value]
            }
          }
        };
  }
1 голос
/ 05 августа 2020

Вы изменяете состояние в своем редукторе, потому что вы копируете только объект верхнего уровня, а затем изменяете содержимое, вложенное внутри этого . Неизменяемые обновления всегда требуют копирования на каждом уровне вложенности как для объектов, так и для массивов.

Правило номер один для написания Redux logi c: Не mutate state .

Вам следует перейти на использование нашего официального пакета Redux Toolkit . Он не только обнаружил бы эти случайные мутации и предупредил вас, createSlice API позволяет вам писать «мутирующий» код, который превращается в безопасные, правильные неизменяемые обновления.

Вы также должны найти время, чтобы прочитать через страницу документации Redux в «Неизменяемых шаблонах обновления» и сообщение Дэйва Седдиа на Полное руководство по неизменяемости в React и Redux .

...