Redux ToolKit:是否可以在 createAsyncThunk 创建的一个动作中从同一个切片中分派其他动作

Joj*_*oji 3 reactjs redux redux-thunk redux-toolkit

我正在使用redux-toolkitwithcreateAsyncThunk来处理异步请求。

我有两种异步操作:

  1. 从 API 服务器获取数据

  2. 更新 API 服务器上的数据

export const updateData = createAsyncThunk('data/update', async (params) => {
  return await sdkClient.update({ params })
})

export const getData = createAsyncThunk('data/request', async () => {
  const { data } = await sdkClient.request()
  return data
})
Run Code Online (Sandbox Code Playgroud)

我把它们extraReducers加到一片里

const slice = createSlice({
  name: 'data',
  initialState,
  reducers: {},
  extraReducers: (builder: any) => {
    builder.addCase(getData.pending, (state) => {
      //...
    })
    builder.addCase(getData.rejected, (state) => {
      //...
    })
    builder.addCase(
      getData.fulfilled,
      (state, { payload }: PayloadAction<{ data: any }>) => {
        state.data = payload.data
      }
    )
    builder.addCase(updateData.pending, (state) => {
      //...
    })
    builder.addCase(updateData.rejected, (state) => {
      //...
    })
    builder.addCase(updateData.fulfilled, (state) => {
      //<--- here I want to dispatch `getData` action to pull the updated data
    })
  },
})
Run Code Online (Sandbox Code Playgroud)

在我的组件中,我有一个按钮可以触发更新操作的调度。但是我在单击按钮后发现,尽管服务器上的数据正在更新,但页面上的数据并未同时更新。

function MyComponent() {
  const dispatch = useDispatch()
  const data = useSelector((state) => state.data)

  useEffect(() => {
    dispatch(getData())
  }, [dispatch])

  const handleUpdate = () => {
    dispatch(updateData())
  }

  return (
    <div>
      <ul>
        // data goes in here
      </ul>
      <button onClick={handleUpdate}>update</button>
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

我尝试添加dispatch(getData())handleUpdate更新后的数据。但是,由于异步 thunk,它不起作用。我想知道是否可以getDataupdateDataie的生命周期动作中调度动作

builder.addCase(updateData.fulfilled, (state) => {
      dispatch(getData())//<--- here I want to dispatch `getData` action to pull the updated data
    })
Run Code Online (Sandbox Code Playgroud)

小智 39

可能它不是实际的,问题已经过时了,但是 的thunkAPI有效负载创建者中有第二个参数createAsyncThunk,因此可以像这样使用它

export const updateData = createAsyncThunk('data/update', async (params, {dispatch}) => {
  const result = await sdkClient.update({ params })
  dispatch(getData())
  return result
})
Run Code Online (Sandbox Code Playgroud)


phr*_*hry 5

首先:请注意,reducer 总是需要是没有副作用的纯函数。所以你永远不能dispatch在那里做任何事情,因为那会产生副作用。即使你能以某种方式设法做到这一点,redux也会警告你。

现在解决手头的问题。

您可以创建一个 thunk 来调度并等待您的updateData呼叫完成,然后调度您的getData呼叫:

export const updateAndThenGet = (params) => async (dispatch) => {
  await dispatch(updateData(params))
  return await dispatch(getData())
}

//use it like this
dispatch(updateAndThenGet(params))
Run Code Online (Sandbox Code Playgroud)

或者,如果这两个步骤总是一起分派,您可以考虑将它们组合起来:

export const updateDataAndGet = createAsyncThunk('data/update', async (params) => {
  await sdkClient.update({ params })
  const { data } = await sdkClient.request()
  return data
})
Run Code Online (Sandbox Code Playgroud)

  • @Valentin 我是 Redux Toolkit 维护者,我知道 `createSlice` 的作用。是的,您可以在那里修改“状态”,但这仍然是“纯粹的”,因为它除了作为参数显式放入函数中的内容之外没有任何副作用。Redux 减速器中永远不允许使用“dispatch”,即使在“createSlice”减速器中也是如此。这是一个副作用。 (5认同)