【问题标题】:My Redux state is not updating even-though the old an new state are not equal我的 Redux 状态没有更新——即使旧的和新的状态不相等
【发布时间】:2020-05-14 13:33:41
【问题描述】:

我的 Redux 状态有问题。我制作了一个应该更新数组中的值的减速器。但是,我相信我遵循了所有不变性原则,但由于某种原因,我的状态没有更新。我什至在 reducer 的末尾添加了一个控制台日志,比较旧的 en 新状态,它返回 false。

我错过了什么吗?

我正在使用 Redux DevTools chrome 插件来检查状态。

状态:

selectedProfileId: mainProfileId,
profiles: {
    [mainProfileId]:{
        name: "Spellbook 1",
        classes: [],
        learnedSpells: {
            cantrip: [],
            first: [],
            second: [],
            third: [],
            fourth: [],
            fifth: [],
            sixth: [],
            seventh: [],
            eighth: [],
            ninth: []
        },
        spellSlots:[
            {slots: 0, used: 0},
            {slots: 0, used: 0},
            {slots: 0, used: 0},
            {slots: 0, used: 0},
            {slots: 0, used: 0},
            {slots: 0, used: 0},
            {slots: 0, used: 0},
            {slots: 0, used: 0},
            {slots: 0, used: 0}
        ]
    }
  }

减速机:

switch (action.type) {
  case actions.SET_SPELL_SLOTS:    
    let newSpellSlotArray = state.profiles[state.selectedProfileId].spellSlots.slice();

    newSpellSlotArray.map((item, index) => {
      if (index !== action.spellslot-1) {
        return item
      }

      let newItem = {
        ...item,
        slots: parseInt(action.count)
      };
      console.log("Updating item:", item, newItem);

      return newItem;
    })

    var newState = {
      ...state,
      profiles: {
        ...state.profiles,
        [state.selectedProfileId]:{
          ...state.profiles[state.selectedProfileId],
          spellSlots: newSpellSlotArray
        }
      }
    }

    console.log((newState == state))

    return newState
  default:
    return state
}

控制台日志:

Updating item: {slots: 0, used: 0}
   slots: 0
   used: 0
 __proto__: Object 
{slots: 5, used: 0}
    slots: 5
    used: 0
    __proto__: Object
spellbookData.js:70
false

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    你的 reducer 坏了,因为你实际上并没有用新值保存数组。

    • spellSlots.slice() 确实会使用所有旧值创建一个新数组引用
    • 但是,newSpellSlotArray.map() 返回一个新数组引用,其中包含 map() 回调返回的所有值,但您的代码当前正在丢弃该新数组,因为它没有分配给变量。
    • 在 return 语句中,spellSlots: newSpellSlotArray 将返回一个包含所有旧数据的新数组,而不是更新后的数据。

    您的代码的短期修复是:

    const newSpellSlotArray = state.profiles[state.selectedProfileId].spellSlots.map( (item, index) => {
      // map logic here
    });
    

    但是,我强烈建议您使用switch to using our official Redux Toolkit package。 RTK 的createSlice API 在内部使用 Immer,它允许您编写“变异”不可变更新。这将使您将整个减速器简化为:

    const profilesSlice= createSlice({
      name: "profiles",
      initialState,
      reducers: {
        spellSlotsUpdated(state, action) {
          const {spellslot, count} = action.payload;
          const item = state.profiles[state.selectedProfileId].spellSlots[spellslot- 1];
          item.slots = parseInt(count);
        }
      }  
    })
    

    如您所见,它更短且更易于阅读。

    【讨论】:

      【解决方案2】:

      修改你的 Reducer,Array.map() 返回你必须存储和使用的新数组

      switch (action.type) {
        case actions.SET_SPELL_SLOTS:    
          let newSpellSlotArray = state.profiles[state.selectedProfileId].spellSlots.map((item, index) => {
            if (index !== action.spellslot-1) {
              return item
            }
      
            let newItem = {
              ...item,
              slots: parseInt(action.count)
            };
            console.log("Updating item:", item, newItem);
      
            return newItem;
          })
      
          var newState = {
            ...state,
            profiles: {
              ...state.profiles,
              [state.selectedProfileId]:{
                ...state.profiles[state.selectedProfileId],
                spellSlots: newSpellSlotArray
              }
            }
          }
      
          console.log((newState == state))
      
          return newState
        default:
          return state
      }
      

      【讨论】:

        猜你喜欢
        • 2021-11-07
        • 1970-01-01
        • 2021-09-08
        • 2017-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-21
        • 1970-01-01
        相关资源
        最近更新 更多