如何在两个不同的Redux切片之间移动数据?

a64a0gku  于 2022-11-24  发布在  其他
关注(0)|答案(2)|浏览(165)

我使用的是最新(截至今天)版本的React + React-Redux。
当我启动我的应用程序时,我加载了一个数据列表,我需要将其存储在一个用于一个目的的切片中。对于本例,是一个表名及其字段的列表。
我还有一个管理UI状态的切片,它只需要****表名来创建子菜单。
包含所有数据的表列表被加载到切片tree中,我只需要将表名复制到一个名为UI的切片中。
我不太清楚在两个同级切片之间移动数据的最佳方式(或正确方式)。

mi7gmzs6

mi7gmzs61#

有三种方法可以达到兄弟切片的状态:

  1. getState在dispatch(action)中为UI切片创建一个动作,getState返回整个存储对象,请参见
export const setUIElements = (payloadOfTheUIDispatch) => (dispatch, getState) => {
  const { sliceNameOfTheTable } = getState();
  const tableData = sliceNameOfTheTable;
  // ... update data as you need:
  dispatch(actionThatUpdatesUISlice(data));
}

然后读取actionThatUpdatesUISlice更新的状态。
1.在创建子菜单的组件中使用useSelector。从tableSliceuiSlice读取:

const tableData = useSelector(state => state.tableData);
  const uiData = useSelector(state => state.ui);

  // create submenu here
  // example: 
  const subMenu = React.useMemo(() => {
    if (!tableData || !uiData) return null;
    return tableData.map(item => <div key={item.id}>{item.name}</div>);
  },[tableData, uiData]);

1.如果您正在执行某种开销很大的计算来为ui切片中的子菜单创建数据,则可以使用createSelector,但如果您不执行任何开销很大的计算,则前两种方法是最佳的:

export const selectSubMenuItems = createSelector(
  state => state.ui,
  state => state.table,
  (uiData, { stateNameOfTableDataInTableSlice }) => {
    const { stateNameFromUISliceThatYouNeed } = uiData;
    const expensiveCalculation = differenceBy(
      stateNameFromUISliceThatYouNeed,
      stateNameOfTableDataInTableSlice.map(item => item.name),
      'id',
    );
    return expensiveCalculation;
  },
);
wkftcu5l

wkftcu5l2#

我最终采取的方法是在第二个切片上添加一个reducer,它捕获与第一个切片相同的动作,因此两者同时获得相同的有效负载,彼此没有依赖性。
但是,如果我可以用一个简单的选择器来解决这个问题(就像我的问题中的评论所建议的那样,它会更好)。
第一切片:

const SliceA = createSlice({
  name: "sliceA",
  initialState: {},
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase("a1/menueData/loaded", (state,action) => {
           //do what I want with action.payload
    }
  }
}


// in a different file

const SliceB = createSlice({
  name: "sliceB",
  initialState: {},
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase("a1/menueData/loaded", (state,action) => {
           //do what I want with action.payload, which is the same one as 
           //in reducer A above
    }
  }
}

相关问题