Redux ToolKit:是否可以在 createAsyncThunk 创建的一个动作中从同一切片分派其他动作
Redux ToolKit: is it possible to dispatch other actions from the same slice in one action created by createAsyncThunk
我正在使用 redux-toolkit
和 createAsyncThunk
来处理异步请求。
我有两种异步操作:
从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())
。但是,由于异步 thunk,它不起作用。我想知道我是否可以在 updateData
的生命周期操作中调度 getData
操作,即
builder.addCase(updateData.fulfilled, (state) => {
dispatch(getData())//<--- here I want to dispatch `getData` action to pull the updated data
})
首先:请注意,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
})
可能它不是实际的并且问题已经过时,但是 createAsyncThunk
的 payload creator 中有 thunkAPI
作为第二个参数,所以它可以像这样使用
export const updateData = createAsyncThunk('data/update', async (params, {dispatch}) => {
const result = await sdkClient.update({ params })
dispatch(getData())
return result
})
我正在使用 redux-toolkit
和 createAsyncThunk
来处理异步请求。
我有两种异步操作:
从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())
。但是,由于异步 thunk,它不起作用。我想知道我是否可以在 updateData
的生命周期操作中调度 getData
操作,即
builder.addCase(updateData.fulfilled, (state) => {
dispatch(getData())//<--- here I want to dispatch `getData` action to pull the updated data
})
首先:请注意,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
})
可能它不是实际的并且问题已经过时,但是 createAsyncThunk
的 payload creator 中有 thunkAPI
作为第二个参数,所以它可以像这样使用
export const updateData = createAsyncThunk('data/update', async (params, {dispatch}) => {
const result = await sdkClient.update({ params })
dispatch(getData())
return result
})