Redux ToolKit:是不是可以在由 createAsyncThunk 创建的一个操作中调度来自同一切片的其他操作

Posted

技术标签:

【中文标题】Redux ToolKit:是不是可以在由 createAsyncThunk 创建的一个操作中调度来自同一切片的其他操作【英文标题】:Redux ToolKit: is it possible to dispatch other actions from the same slice in one action created by createAsyncThunkRedux ToolKit:是否可以在由 createAsyncThunk 创建的一个操作中调度来自同一切片的其他操作 【发布时间】:2020-12-10 11:27:39 【问题描述】:

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

我有两种异步操作:

    从 API 服务器获取数据

    更新 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
)

然后我将它们添加到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
    )
  ,
)

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

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>
  )

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

builder.addCase(updateData.fulfilled, (state) => 
      dispatch(getData())//<--- here I want to dispatch `getData` action to pull the updated data
    )

【问题讨论】:

【参考方案1】:

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

export const updateData = createAsyncThunk('data/update', async (params, dispatch) => 
  const result = await sdkClient.update( params )
  dispatch(getData())
  return result
)

【讨论】:

【参考方案2】:

首先:请注意,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))

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

export const updateDataAndGet = createAsyncThunk('data/update', async (params) => 
  await sdkClient.update( params )
  const  data  = await sdkClient.request()
  return data
)

【讨论】:

您的意思是“await dispatch(updateDataAndGet (params))”而不是“await dispatch(updateData(params))”希望这是一个错字吗? 这是两个不同的示例解决方案。第一个分别引用了 OP 的 updateData thunk 和 getData thunk。第二个将它们组合成一个新的名称updateDataAndGet

以上是关于Redux ToolKit:是不是可以在由 createAsyncThunk 创建的一个操作中调度来自同一切片的其他操作的主要内容,如果未能解决你的问题,请参考以下文章

Redux-Toolkit createAsyncThunk with Typescript

Redux工具包 - Redux Toolkit的异步操作(发送网络请求)

关于 redux-toolkit redux-saga 的一些问题

Redux工具包 - Redux Toolkit的基本使用

为一个大项目迁移到 redux-toolkit

WebStorm 中的 Redux-toolkit 操作参数