使用 redux 工具包时定义操作中的副作用(不是异步 thunk)的正确方法是什么?
What is a proper way of defining side effects in action(not async thunks) when using redux toolkit?
目前我正在使用 Typescript 深入研究 Redux Toolkit,但我遇到了注销操作。它基本上根本不应该有任何有效载荷,但应该修改 localStorage 和 axios 配置。
我知道两种工作方式略有不同。
一种是在 createSlice
:
中使用 prepare
回调定义 reducer
const authSlice = createSlice({
name: "authentication",
initialState,
reducers: {
logout: {
reducer: () => initialState,
prepare: () => {
api.logout();
return { payload: undefined, error: undefined, meta: undefined };
},
},
},...
在这种情况下,准备回调的类型签名强制我显式 return payload
、error
和 meta
属性。
另一种方法是使用 createAction
和 prepare
回调:
export const logout = createAction("authentication/logout", () => {
api.logout();
return { payload: undefined };
});
这是一个更好看的解决方案。至少我不必通过 error
和 meta
。但仍然被迫returnpayload
,即使它不需要。
有点困惑为什么 prepare
函数签名不同,但这不是重点。
我的问题是您将如何处理此类情况。也许我做错了什么?
我知道还有使用中间件的选项,但是设置只处理一个操作的中间件看起来像是一项开销。
我敢打赌 api.logout
是异步函数。
如果是async
,你应该使用createAsyncThunk而不是createAction
请看例子:
import { createAsyncThunk } from '@reduxjs/toolkit'
const api = async () => { }
const increment = createAsyncThunk('counter/increment', api)
const action = increment() // AsyncThunkAction<void, void, {}>
你在这里有点混淆术语 - 并且遗漏了一个重要的术语;)
action 是具有 type
属性 的对象。你永远不能在那里执行代码。
action creator 是 returns 一个 action 的函数。您可以在此处执行代码,但它会在分派结果操作之前执行。
async thunk 是 thunk 的一种特殊形式,它将生命周期操作 (pending/fulfilled/rejected) 附加到 thunk。确切地说,createAsyncThunk
函数创建了一个 async thunk action creator - 一个创建你可以 dispatch 的东西的函数触发。
那么,缺少的东西:什么是 thunk?
thunk 是一个被分派的函数 - 然后由 redux-thunk 中间件执行。该函数将 dispatch
作为第一个参数传递, getState
作为第二个参数传递,因此您可以在必要时从那里触发更多与 redux 相关的东西。
所以你正在寻找一个thunk。通常,这些都是用 action creator 编写的,因此您正在寻找 thunk action creator。
const logout = (potentiallySomeArgument) => (dispatch, getState) => {
api.logout(potentiallySomeArgument);
// maybe you also want to dispatch an action to clear state
dispatch(userSlice.clear())
}
这将像任何其他操作一样被分派,因此功能与您的组件完全无关:
dispatch(logout("whatever"))
目前我正在使用 Typescript 深入研究 Redux Toolkit,但我遇到了注销操作。它基本上根本不应该有任何有效载荷,但应该修改 localStorage 和 axios 配置。 我知道两种工作方式略有不同。
一种是在 createSlice
:
prepare
回调定义 reducer
const authSlice = createSlice({
name: "authentication",
initialState,
reducers: {
logout: {
reducer: () => initialState,
prepare: () => {
api.logout();
return { payload: undefined, error: undefined, meta: undefined };
},
},
},...
在这种情况下,准备回调的类型签名强制我显式 return payload
、error
和 meta
属性。
另一种方法是使用 createAction
和 prepare
回调:
export const logout = createAction("authentication/logout", () => {
api.logout();
return { payload: undefined };
});
这是一个更好看的解决方案。至少我不必通过 error
和 meta
。但仍然被迫returnpayload
,即使它不需要。
有点困惑为什么 prepare
函数签名不同,但这不是重点。
我的问题是您将如何处理此类情况。也许我做错了什么?
我知道还有使用中间件的选项,但是设置只处理一个操作的中间件看起来像是一项开销。
我敢打赌 api.logout
是异步函数。
如果是async
,你应该使用createAsyncThunk而不是createAction
请看例子:
import { createAsyncThunk } from '@reduxjs/toolkit'
const api = async () => { }
const increment = createAsyncThunk('counter/increment', api)
const action = increment() // AsyncThunkAction<void, void, {}>
你在这里有点混淆术语 - 并且遗漏了一个重要的术语;)
action 是具有 type
属性 的对象。你永远不能在那里执行代码。
action creator 是 returns 一个 action 的函数。您可以在此处执行代码,但它会在分派结果操作之前执行。
async thunk 是 thunk 的一种特殊形式,它将生命周期操作 (pending/fulfilled/rejected) 附加到 thunk。确切地说,createAsyncThunk
函数创建了一个 async thunk action creator - 一个创建你可以 dispatch 的东西的函数触发。
那么,缺少的东西:什么是 thunk?
thunk 是一个被分派的函数 - 然后由 redux-thunk 中间件执行。该函数将 dispatch
作为第一个参数传递, getState
作为第二个参数传递,因此您可以在必要时从那里触发更多与 redux 相关的东西。
所以你正在寻找一个thunk。通常,这些都是用 action creator 编写的,因此您正在寻找 thunk action creator。
const logout = (potentiallySomeArgument) => (dispatch, getState) => {
api.logout(potentiallySomeArgument);
// maybe you also want to dispatch an action to clear state
dispatch(userSlice.clear())
}
这将像任何其他操作一样被分派,因此功能与您的组件完全无关:
dispatch(logout("whatever"))