Redux Toolkit将状态保存到本地存储

11

我正在使用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

有人能告诉我这是否是一个好主意,如果不是,有没有其他正确的方法。


1
我投票关闭这个问题,因为它应该在https://codereview.stackexchange.com上发布。 - Ian Kemp
1个回答

13
你走在正确的道路上,但是还需要做出一些改变:

访问状态

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

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

您的effect函数会接收两个参数:触发该效果的actionlistenerApi对象,该对象使您可以访问getState()许多其他实用程序

监听器中间件不知道存储的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 操作。监听器可以检测匹配操作的 几种不同的方式。我们将使用 matcher 属性,而不是只能匹配单个操作的 actionCreator。我们借助于 isAnyOf 实用程序 创建一个匹配器函数。
我们的最终中间件如下所示:
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)
    )
});

完整的 CodeSandbox 演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接