Angular 7 + NGRX:如何用Effect监听设置变更并存入LocalStorage
解决NGRX设置变更后自动存储到LocalStorage的Effect方案
你遇到的问题根源在于构造函数中的Store订阅会在INIT Effect执行前触发,导致Store的初始状态提前覆盖了LocalStorage里的值,进而让INIT Effect读取不到正确的本地存储数据。
其实完全可以不用手动订阅Store,而是利用NGRX Effect的特性,直接监听所有设置变更的Action,在动作触发后执行存储操作,这样既符合NGRX的数据流规范,又能避免初始化顺序的问题。
具体实现方案
修改你的SettingsEffects类,添加一个专门用于存储设置的Effect,监听所有设置相关的Action类型,然后获取最新的状态并写入LocalStorage:
import { Injectable } from '@angular/core'; import { Actions, ROOT_EFFECTS_INIT, ofType, createEffect } from '@ngrx/effects'; import { Store, select } from '@ngrx/store'; import { of, EMPTY } from 'rxjs'; import { switchMap, withLatestFrom, tap } from 'rxjs/operators'; import * as featureActions from './actions'; // 替换为你的actions实际路径 import * as featureSelector from './selectors'; // 替换为你的selectors实际路径 import { IAppState } from '../app.state'; // 替换为你的全局state类型 @Injectable() export class SettingsEffects { constructor( private actions$: Actions, private localStorageService: LocalStorageService, private store$: Store<IAppState> ) {} // 初始化加载LocalStorage的Effect(保留你的原有逻辑) init$ = createEffect(() => this.actions$.pipe( ofType(ROOT_EFFECTS_INIT), switchMap(() => { const settings = this.localStorageService.retrieve('settings'); if (settings) { return of(new featureActions.SetSettings({ settings })); } else { return EMPTY; } }) ) ); // 监听设置变更动作,自动存储到LocalStorage saveSettingsToLocalStorage$ = createEffect(() => this.actions$.pipe( // 监听所有设置相关的Action类型 ofType( featureActions.ActionTypes.SetSettings, featureActions.ActionTypes.SetNavigationSettings ), // 获取最新的Settings状态 withLatestFrom(this.store$.pipe(select(featureSelector.selectSettingsState))), // 执行存储操作({ dispatch: false }表示这个Effect不触发新的Action) tap(([_, settings]) => { this.localStorageService.store('settings', settings); }) ), { dispatch: false } ); }
方案说明
- 监听目标Action:通过
ofType指定要监听的两个设置变更动作,只有当这两个动作被dispatch时,这个Effect才会执行。 - 获取最新状态:使用
withLatestFrom操作符,在Action触发后获取Store中最新的Settings状态,确保存储的是最新的完整设置。 - 非派发Effect:添加
{ dispatch: false }配置,因为这个Effect只负责执行存储副作用,不需要触发新的Action,符合NGRX的最佳实践。
为什么这个方案能解决你的问题?
- 这个Effect只会在设置变更动作被触发后执行,不会在应用初始化时提前运行,避免了初始状态覆盖LocalStorage的问题。
- 当INIT Effect从LocalStorage加载设置并dispatch
SetSettings动作时,这个存储Effect会触发,但此时存储的是刚从LocalStorage读取的设置,相当于做了一次“同步”,不会破坏原有数据。 - 后续用户修改设置时,只要触发
SetSettings或SetNavigationSettings动作,存储逻辑就会自动执行,完美实现你的需求。
内容的提问来源于stack exchange,提问作者Crocsx
相关产品推荐
相关产品推荐

