Redux Toolkit:从 extraReducers 侦听器分派动作?

IT技术 reactjs redux react-redux redux-toolkit
2021-05-06 00:19:45

我想知道是否可以(或一个好的做法)dispatch(someDumbAction())从 extraReducer调用

例如,我setData()reducers对象 from 中有一个操作createSlice我想setData()直接在我的组件中调用但我也想在extraReducer侦听器中调用它,以便重用 reducer 逻辑,如下所示:

// Thunk Action
export const getData = createAsyncThunk('data/getData', async (params) => {
  return await api.get({ params })
})

// Slice creation
const slice = createSlice({
  name: 'data',
  initialState: [],
  reducers: {
    setData: (state, { payload }) => {
       state.push(payload);
    })
  },
  extraReducers: (builder: any) => {
    builder.addCase(getData.pending, (state) => {
      //...
    })
    builder.addCase(getData.rejected, (state) => {
      //...
    })
    builder.addCase(getData.fulfilled, (state, { payload }) => {
      // Here I want to dispatch `setData` action, in order to reuse that logic
      // dispatch(setData(payload));
      
    })
  },
})

// In any component: dispatch(setData([...]);
1个回答

。Reducers永远不能分派动作

https://redux.js.org/style-guide/style-guide#reducers-must-not-have-side-effects

但是,看起来您在这里真正要求的是能够在多种情况下运行相同的状态更新逻辑步骤。

您可以将逻辑定义为独立的 reducer 函数,并在两种情况下重用它:

function addItem(state, action) {
  state.push(action.payload);
}

const slice = createSlice({
  name: 'data',
  initialState: [],
  reducers: {
    setData: addItem
  },
  extraReducers: (builder: any) => {
    builder.addCase(getData.pending, (state) => {
      //...
    })
    builder.addCase(getData.rejected, (state) => {
      //...
    })
    builder.addCase(getData.fulfilled, addItem)
  },
})

您还可以将函数定义为 的一部分reducers,然后在extraReducers处理程序中引用它

const slice = createSlice({
  name: 'data',
  initialState: [],
  reducers: {
    setData: (state, { payload }) => {
       state.push(payload);
    })
  },
  extraReducers: (builder: any) => {
    builder.addCase(getData.pending, (state) => {
      //...
    })
    builder.addCase(getData.rejected, (state) => {
      //...
    })
    builder.addCase(getData.fulfilled, (state, action) => {
      slice.caseReducers.setData(state, action);
    })
  },
})