首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从减速机挂钩保存到localStorage

从减速机挂钩保存到localStorage
EN

Stack Overflow用户
提问于 2019-01-24 20:37:11
回答 2查看 3.8K关注 0票数 6

我正在使用useReducer钩子来保存一些全局状态。因为我想在浏览器关闭时保存一些设置,所以我将这些设置保存到本地存储中。

目前,我使用分派保存设置,并使用一个单独的函数将其保存到本地存储,但如果设置在分派后自动保存就更好了。(有时我忘记保存到本地存储,并且状态/本地存储之间存在差异)

从本地存储中读取状态不是问题。为此,我在useReducer钩子中使用了initialState参数。

我认为答案是不这样做,但有什么替代方案呢?(不使用redux)

EN

回答 2

Stack Overflow用户

发布于 2019-01-24 20:45:15

我认为让一个服务负责在localStorage中存储数据是明智的。因此,您可能希望创建一个具有get和set函数的服务。您可以在redux中从effect调用服务。

在我看来,减速器是用来改变状态的。

您还可以使用rxjs等待reducer更新您的状态,然后获取它并使用您的服务将其保存到localStorage。

顺便说一句,依赖于你的需求,我真的看不出你为什么不应该在localStorage中存储数据,只要你记住你的redux状态是你唯一的事实。在我看来,将数据存储在某个地方以在初始化时恢复该状态是一个很好的方法。

下面是一个使用ngrx的示例:

代码语言:javascript
复制
@Effect()
myAction$: Observable<Action> = this.actions$.pipe(
  ofType<MyAction>(actions.myAction),
  debounceTime(300),
  switchMap((action) =>
    this.service.post(action.dto).pipe(
      map((response: SomeDto) => {
        // This updates the state using a reducer
        return new CreateShortenedLinkSuccess(response);
      }),
      tap((value) => {
        // Here, you can use the value param, to save
        // changes to localStorage
        this.router.navigate([`/mgmt/link/${value.dto.id}`]);
      }),
      catchError((response: HttpErrorResponse) => {
        // Do scary stuff
      })
    )
  )
);
票数 1
EN

Stack Overflow用户

发布于 2020-01-16 20:30:50

我发现@Zaid Crouch是一个很棒的工具,但它不能处理来自不同窗口(tab/iframe/popup)的本地存储更新。

代码语言:javascript
复制
import { useReducer, useEffect, Dispatch } from 'react'

// Credits: https://stackoverflow.com/questions/54346866/save-to-localstorage-from-reducer-hook
export type ReducerType<T> = (state: T, action: ActionType) => (T)
export type InitType<T> = (state: T) => void
export interface ActionType {
    type: string
}

var dispatcher:Dispatch<ActionType> | null = null

const LOCAL_STORAGE_UPDATED_IN_A_DIFFERENT_WINDOW = "LOCAL_STORAGE_UPDATED_IN_A_DIFFERENT_WINDOW"
export function useLocallyPersistedReducer<T>
    (reducer: ReducerType<T>, defaultState: T, storageKey: string, init?:InitType<T>) : [T, Dispatch<ActionType>] {

    const reducerWrapper = (status: T, action: ActionType) => {
        switch (action.type){
            case LOCAL_STORAGE_UPDATED_IN_A_DIFFERENT_WINDOW:
                const statusReadFromLocalStorage = JSON.parse(localStorage.getItem(storageKey) || "{}")
                return statusReadFromLocalStorage
            default: return reducer(status, action)
        }
    }

    const [state, dispatch] = useReducer(reducerWrapper, defaultState, (defaultState) => {
        const persisted = JSON.parse(localStorage.getItem(storageKey) as string)
        return persisted !== null
            ? persisted
            : init ? init(defaultState) : defaultState
    })

    // NOTE Even if this codes runs multiple time we add only one event listener as long as the callback is singleton
    dispatcher = dispatch
    window.addEventListener('storage', listenForStorageChangesInOtherWindows, {once: true});

    useEffect(() => {
        localStorage.setItem(storageKey, JSON.stringify(state))
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [localStorage, storageKey, state])

    return [state, dispatch]
}

const listenForStorageChangesInOtherWindows = (key: any) => {
    dispatcher && dispatcher({type: LOCAL_STORAGE_UPDATED_IN_A_DIFFERENT_WINDOW})
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54346866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档