使用 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 payloaderrormeta 属性。

另一种方法是使用 createActionprepare 回调:

export const logout = createAction("authentication/logout", () => {
  api.logout();
  return { payload: undefined };
});

这是一个更好看的解决方案。至少我不必通过 errormeta。但仍然被迫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, {}>

Playground

你在这里有点混淆术语 - 并且遗漏了一个重要的术语;)

action 是具有 type 属性 的对象。你永远不能在那里执行代码。

action creator 是 returns 一个 action 的函数。您可以在此处执行代码,但它会在分派结果操作之前执行。

async thunkthunk 的一种特殊形式,它将生命周期操作 (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"))