【问题标题】:Redux: Add/remove from nested object/array, without mutating?Redux:从嵌套对象/数组中添加/删除,没有变异?
【发布时间】:2016-08-26 08:34:22
【问题描述】:

我认为assign 应该创建一个新对象,这就是我在减速器中这样做的原因:

    case types.ADD_ATTRIBUTE:
      var newState = Object.assign({}, state)
      newState.attributes[action.industry].push(action.attribute)
      return Object.assign({}, state, newState);

    case types.REMOVE_ATTRIBUTE:
      var newState = Object.assign({}, state)
      var removeIndex = newState.attributes[action.industry].indexOf(action.attribute)
      newState.attributes[action.industry].splice(removeIndex, 1)
      return Object.assign({}, state, newState);

但是,当我这样做时,组件不会触发更新 (componentWillReceiveProps)。它确实收到了新的 props,但 react-redux 内部的 shouldComponentUpdate 没有检测到更改。

我在这里做错了什么?

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    如果您想重新渲染包含attributes[action.industry] 的对象,您需要像处理状态一样重新创建此数组。

    case types.ADD_ATTRIBUTE:
      return {
        ...state,
        attributes: {
          ...state.attributes,
          [action.industry]: [...state.attributes[action.industry], action.attribute]
        }
      }
    
    case types.REMOVE_ATTRIBUTE:
      const removeIndex = newState.attributes[action.industry].indexOf(action.attribute)
      return {
        ...state,
        attributes: {
          ...state.attributes,
          [action.industry]: [
              ...state.attributes[action.industry].slice(0, removeIndex), 
              ...state.attributes[action.industry].slice(removeIndex + 1)
            ]
          }
       }
    

    【讨论】:

      【解决方案2】:

      我最终确定了这一点:(使用一些 ES6 魔法)

        case types.ADD_ATTRIBUTE:
            let newAttrState = state.attributes[action.industry].slice()
            newAttrState.push(action.attribute)
            return Object.assign({}, state, { attributes: { [action.industry]: newAttrState }} );
      
        case types.REMOVE_ATTRIBUTE:
            var newAttrState = state.attributes[action.userIndustry].slice()
            let removeIndex = newAttrState.indexOf(action.attribute)
            newAttrState.splice(removeIndex, 1)
            return Object.assign({}, state, { attributes: { [action.userIndustry]: newAttrState }} );
      

      *更新:我现在意识到,它覆盖了整个 attributes 对象,只有一个动态键控数组,而我需要维持存储在该对象中的其他数组...

      【讨论】:

        【解决方案3】:

        React-redux 的shouldComponentUpdate() 对状态进行浅比较,以决定是否渲染。这种浅比较只检查对象的一个​​级别深度,这意味着如果您不更改状态本身的引用或其任何一级属性,它不会触发组件的更新。

        您的数组深深嵌套在state.attributes[action.industry] 中,并且您的操作不会修改状态或属性,因此 react-redux 不会更新您的组件。为了解决您的问题,您需要更改attributes[action.industry],创建一个新数组(例如,使用Array.concat() 代替Array.push() 或使用attributes[action.industry] = [...attributes[action.industry], action.attribute ] 中的扩展运算符

        或者,如果您使用有状态组件,您可以创建自己的 shouldComponentUpdate() 版本,该版本会考虑 attributes 属性以决定是否渲染。

        【讨论】:

          【解决方案4】:

          以下是处理types.ADD_ATTRIBUTE 案例的方法:

          使用 Object.assign:

          const newActionIndustry = state.attributes[action.industry].concat(action.attribute)
          
          const newAttributes = Object.assign({}, state.attributes, {
            [action.industry]: newActionIndustry
          })
          
          const newState =  Object.assign({}, state, {
            attributes: newAttributes
          })
          

          使用此代码自行处理types.REMOVE_ATTRIBUTE 案例。

          【讨论】:

          • 这行得通,但是我看不出这两个例子之间的区别? (都使用 ES6?)
          • 我仍然没有看到任何传播运算符,或者这两个代码有任何区别......
          猜你喜欢
          • 1970-01-01
          • 2018-02-06
          • 2020-12-07
          • 2021-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-30
          相关资源
          最近更新 更多