Arrays 如何在ReactJS reducer中正确更新redux状态?

Arrays 如何在ReactJS reducer中正确更新redux状态?,arrays,reactjs,redux,react-redux,Arrays,Reactjs,Redux,React Redux,我的Redux数据存储中有以下结构: { filterData: { 22421: { filterId: 22421, selectedFilters: [ { filterName: 'gender', text: 'Male', value: 'male'

我的Redux数据存储中有以下结构:

{
    filterData: {
        22421: {
            filterId: 22421,
            selectedFilters: [
                {
                    filterName: 'gender',
                    text: 'Male',
                    value: 'male'
                },
                {
                    filterName: 'gender',
                    text: 'female',
                    value: 'female'
                }
            ] 
        }   
        22422: {
            filterId: 22422,
            selectedFilters: [
                {
                    filterName: 'colour',
                    text: 'Blue',
                    value: 'blue'
                },
                {
                    filterName: 'animal',
                    text: 'sheep',
                    value: 'Sheep'
                }
            ] 
        }   

有人能告诉我使用正确的方法来更新selectedFilters数组而不直接改变状态吗?i、 e.如何在给定filterId的selectedFilters数组中添加/删除元素?

通常使用非变异(即返回新对象,而不是修改现有对象)运算符和函数来完成:

  • )用于对象和数组(用于添加和编辑)
  • ,对于数组(用于编辑和删除)
  • 用于对象(用于编辑和添加)
你必须在每一个层次上都这样做,直到最后一个层次发生变化。在您的情况下,如果要更改其中一个对象上的
selectedFilters
,您必须执行以下操作:

// Assuming you're inside a reducer function.
case SOME_ACTION:
  // Returning the new state object, since there's a change inside.
  return {
    // Prepend old values of the state to this new object.
    ...state,

    // Create a new value for the filters property,
    // since—again—there's a change inside.
    filterData: {
      // Once again, copy all the old values of the filters property…
      ...state.filters,

      // … and create a new value for the filter you want to edit.
      // This one will be about removal of the filter.
      22421: {
        // Here we go again with the copy of the previous value.
        ...state.filters[22421],

        // Since it's an array and we want to remove a value,
        // the filter method will work the best.
        selectedFilters: 
          state.filters[22421].selectedFilters.filter(
            // Let's say you're removing a filter by its name and the name
            // that needs to be removed comes from the action's payload.
            selectedFilter => selectedFilter.name !== action.payload
          )
      },
      // This one could be about addition of a new filter.
      22422: {
        ...state.filters[22422],

        // Spread works best for additions. It returns a new array
        // with the old values being placed inside a new one.
        selectedFilters: [
           // You know the drill.
          ...state.filters[22422].selectedFilters,

          // Add this new filter object to the new array of filters.
          {
            filterName: 'SomeName',
            text: 'some text',
            value: action.value // Let's say the value comes form the action.
          }
        ]
      },
    }
  }
此常量“复制旧值”是确保保留嵌套对象中的值所必需的,因为“排列”操作符以浅层方式复制属性

const someObj = {a: {b: 10}, c: 20}
const modifiedObj = {...someObj, a: {d: 30}}
// modifiedObj is {a: {d: 30}, c: 20}, instead of
// {a: {b: 10, d: 30}, c: 20} if spread created a deep copy.

正如你所看到的,这是一个有点平凡的事情。解决这个问题的一个方法是创建某种嵌套的reducer函数,这些函数将在独立的状态树上工作。然而,有时最好不要重新发明风团,使用已经可以用来解决这些问题的工具。例如。

如果您想使用专用库来管理不可变状态(如另一个答案中建议的),请查看


我发现这个库比Immutable.js更易于使用(而且包的大小也会更小)

感谢您的全面回复。我试图在向数组添加元素时让它工作,所以我尝试使用您提供的代码的这一部分。但是,我收到以下错误消息:“TypeError:无法将undefined或null转换为object”,selectedFilters突出显示。很难说,谢谢你的帮助。现在我明白了,我在响应中使用了
filters
而不是
filterData
,所以这是第一条线索。第二个是示例中应该有
[…state.filters[22422].selectedFilters、/*new filter*/]
(缺少
selectedFilters
访问)。我已经解决了这两个问题,也许这会对你有所帮助。如果没有,您必须显示您的代码。谢谢您的帮助。我成功地解决了这个问题,这是由于我向一个操作传递了一个错误的值造成的。