如何在 React 应用程序中使用 redux 工具包更新不同减速器(切片)中的嵌套项目

How do I update a nested Item in a different reducer (slice) with redux toolkit in a React app

我有以下代码(我删除了大部分代码以使其更容易理解 - 但一切正常):

“角色”减速器:

 // some async thunks      
        
   const rolesSlice = createSlice({
           name: "role",
           initialState,
           reducers: { // some reducers here  },
           extraReducers: {
             // a bunch of extraReducers
             [deleteRole.fulfilled]: (state, { payload }) => {
               state.roles = state.roles.filter((role) => role._id !== payload.id);
               state.loading = false;
               state.hasErrors = false;
             },
           },
         });
export const rolesSelector = (state) => state.roles;

export default rolesSlice.reducer;

“场景”减速器:

    // some async thunks
    
    const scenesSlice = createSlice({
      name: "scene",
      initialState,
      reducers: {},
      extraReducers: {
        [fetchScenes.fulfilled]: (state, { payload }) => {
          state.scenes = payload.map((scene) => scene);
          state.loading = false;
          state.scenesFetched = true;
        }
    }

export const scenesSelector = (state) => state.scenes;

export default scenesSlice.reducer;

带有按钮和 handleDelete 函数的组件:

// a react functional component

function handleDelete(role) {

 // some confirmation code

      dispatch(deleteRole(role._id));
  }

我的场景模型(和存储状态)如下所示:

   [
    {
     number: 1,
     roles: [role1, role2]
    },
    {
    number: 2,
    roles: [role3, role5]
    }
   ]

我想要实现的是,当一个角色被删除时,state.scenes 得到更新(映射场景并过滤掉所有被删除角色的出现)。

所以我的问题是,如何在不从我的组件调用两个不同操作的情况下更新状态(这是推荐的方法?)

提前致谢!

您可以使用 createSliceextraReducers 属性 来响应在另一个切片中定义的操作,或者在切片外部定义的操作,因为它们在这里。

您想遍历每个场景并从角色数组中删除已删除的角色。如果您只是用最容易编写的过滤版本替换每个数组。但它会导致不必要的重新渲染,因为您要替换的某些数组没有更改。相反,我们可以使用 .findIndex().splice(),类似于 this example.

extraReducers: {
  [fetchScenes.fulfilled]: (state, { payload }) => { ... }
  [deleteRole.fulfilled]: (state, { payload }) => {
    state.scenes.forEach( scene => {
      // find the index of the deleted role id in an array of ids
      const i = scene.roles.findIndex( id => id === payload.id );
      // if the array contains the deleted role
      if ( i !== -1 ) {
        // remove one element starting from that position
        scene.roles.splice( i, 1 )
      }
    })
  }
}