【问题标题】:Redux Toolkit save state to local storageRedux Toolkit 将状态保存到本地存储
【发布时间】:2022-10-20 12:35:04
【问题描述】:

我正在使用 redux-toolkit,并且我试图在每次更新商店后将我的状态保存到本地存储,而不使用任何第三方库。原因是 redux-persist 不再更新,我不知道有什么好的选择。经过大量时间寻找解决方案后,我想出了使用createListenerMiddleware

import { configureStore, createListenerMiddleware } from "@reduxjs/toolkit";
import counterSlice, { decrement, increment } from "../Slices/counterSlice";

const listenerMiddleware = createListenerMiddleware()
listenerMiddleware.startListening({
    actionCreator: increment,
    effect: () => (
        localStorage.setItem('count', JSON.stringify(store.getState().counter))
    )
})
const listenerMiddleware2 = createListenerMiddleware()
listenerMiddleware.startListening({
    actionCreator: decrement,
    effect: () => (
        localStorage.setItem('count', JSON.stringify(store.getState().counter))
    )
})
const counterState = JSON.parse(localStorage.getItem('count') || "null")
export const store = configureStore({
    preloadedState: {
        counter: counterState === null ? { value: 0 } : counterState
    },
    reducer: {
        counter: counterSlice
    },
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(listenerMiddleware2.middleware, listenerMiddleware.middleware)
})

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

有人可以告诉我这是否是一个好主意,如果不是,是否有任何其他方法可以正确地做到这一点。

【问题讨论】:

    标签: reactjs typescript react-redux redux-toolkit


    【解决方案1】:

    您走在正确的轨道上,但有一些变化:

    访问状态

    您应该从effect 回调的参数中访问getState() 函数,而不是直接使用store 变量来调用getState()

    effect: (action: Action, listenerApi: ListenerApi) => void | Promise<void>
    

    您的 effect 函数使用两个参数调用:触发效果的 action 和允许您访问 getState()many other utilitieslistenerApi 对象。

    侦听器中间件不知道存储的 TypeScript 类型,因此您需要以某种方式使其知道。一种方法是在listenerApi.getState() 调用上使用内联as 断言。

    listenerMiddleware.startListening({
      actionCreator: increment,
      effect: (action, listenerApi) =>
        localStorage.setItem("count", JSON.stringify((listenerApi.getState() as RootState).counter))
    });
    

    您还可以按照文档的TypeScript Usage 部分并使用TypedStartListening 实用程序类型。

    处理多个动作

    您不需要多个侦听器中间件实例,因为您可以将多个侦听器附加到同一个中间件。在同一个 listenerMiddleware 变量上简单调用 startListening 多次。

    但是在这种情况下,您只需要一个startListening 电话!您的两个案例已经有相同的effect 回调。但是我们需要能够匹配incrementdecrement 动作。有a few different ways,监听器可以检测到匹配的动作。我们将使用matcher 属性,而不是使用只能匹配单个操作的actionCreator。我们在isAnyOf utility 的帮助下创建了一个匹配器函数。

    我们最终的中间件如下所示:

    import { createListenerMiddleware, isAnyOf } from "@reduxjs/toolkit";
    import { decrement, increment } from "./slice";
    import type { RootState } from "./index";
    
    export const listenerMiddleware = createListenerMiddleware();
    listenerMiddleware.startListening({
      matcher: isAnyOf(increment, decrement),
      effect: (action, listenerApi) =>
        localStorage.setItem(
          "count",
          JSON.stringify((listenerApi.getState() as RootState).counter)
        )
    });
    

    Complete CodeSandbox Demo

    【讨论】:

    • 很好的答案和解释!谢谢 !
    猜你喜欢
    • 1970-01-01
    • 2018-07-14
    • 2020-07-22
    • 1970-01-01
    • 2016-04-21
    • 2019-12-12
    • 1970-01-01
    • 2017-02-23
    • 2020-08-28
    相关资源
    最近更新 更多