【问题标题】: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 来处理异步请求。

我有两种异步操作:

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

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

【问题讨论】:

    标签: reactjs redux redux-thunk redux-toolkit


    【解决方案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
      猜你喜欢
      • 2021-09-01
      • 1970-01-01
      • 2017-05-22
      • 2021-04-12
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      相关资源
      最近更新 更多