如何重置ngrx/store的所有状态?
Posted
技术标签:
【中文标题】如何重置ngrx/store的所有状态?【英文标题】:How to reset all states of ngrx/store? 【发布时间】:2017-01-12 09:26:01 【问题描述】:我正在使用带有ngrx/store 的Angular 2。我想在用户发送 USER_LOGOUT
时重置整个商店状态。
我阅读了 Dan Abramov 对 How to reset the state of a Redux store? 的回答,但我不知道如何正确编写 rootReducer
以及在使用 ngrx/store 时将其放在何处。
或者在ngrx/store中有没有其他方法可以处理这个问题?
bootstrap(App, [
provideStore(
compose(
storeFreeze,
storeLogger(),
combineReducers
)(
router: routerReducer,
foo: fooReducer,
bar: barReducer
)
)
]);
【问题讨论】:
【参考方案1】:在 ngrx/store 4.x 中,这可以通过 Meta-reducers 来完成。据我了解,所有动作都经过元缩减器,然后才移交给特征缩减器。这让我们有机会首先更改/重置状态。
这是一个例子。
这是我的 metareducer 函数:如果动作是 LOGOUT 类型,则重新初始化状态。
function logout(reducer)
return function (state, action)
return reducer(action.type === LOGOUT ? undefined : state, action);
您将在下面看到如何配置 metareducer 以及 feature reducer。如果 metareducer 超过 1 个,则从右到左计算它们
StoreModule.forRoot(rooms: roomReducer, user: userReducer, metaReducers: [logout])
最后,我还有一个@effect 导航到登录页面
@Effect(dispatch: false) logout: Observable<Action> =
this.actions$.ofType(LOGOUT)
.do(() =>
// ... some more stuff here ...
this.router.navigate(['/login page'])
);
【讨论】:
这应该是公认的答案,因为现在 4.x 有一些变化。 这对于 Angular 8 和 Ngrx-8 仍然完全有效。【参考方案2】:此答案特定于 ngrx 版本 2。问题有 another, more recent answer,它解释了如何使用 ngrx 版本 4 完成相同的操作。
compose
构建 ngrx root reducer。
传递给compose
的参数是返回reducer 的函数——由reducer 组成,它们本身作为参数传递。您可以像这样编写商店的重置:
import compose from "@ngrx/core/compose";
...
bootstrap(App, [
provideStore(
compose(
storeFreeze,
storeLogger(),
(reducer: Function) =>
return function(state, action)
if (action.type === 'USER_LOGOUT')
state = undefined;
return reducer(state, action);
;
,
combineReducers
)(
router: routerReducer,
foo: fooReducer,
bar: barReducer
)
)
]);
请注意,这将重置商店的所有状态 - 包括 router
。如果这不是您想要的,您可以调整示例。
随着NgModule
的引入,引导发生了变化,但您仍然将组合的reducer 传递给provideStore
:
import compose from "@ngrx/core/compose";
import StoreModule from "@ngrx/store";
@NgModule(
...
imports: [
...
StoreModule.provideStore(compose(...))
],
...
【讨论】:
如何在当前版本的ngrx中做到这一点? @Daskus 你将组合reducer 传递给StoreModule.provideStore
。查看更新后的答案。
@cartant 如何使用forRoot
和forFeature
在最新的ngrx 版本上执行此操作?我在 angularindepth.com 上关注你,我希望能有一篇关于此的文章。
@AndreaM16 请参阅下面 David Bulté 的回答。【参考方案3】:
与@ngrx/store": "^4.0.3" 这略有不同,因为有小的变化,所以我的'清除状态'看起来像这样
import ActionReducerMap from '@ngrx/store';
import ActionReducer, MetaReducer from '@ngrx/store';
export const rootReducer: ActionReducerMap<StoreStates> =
points: pointsReducer,
...
;
export function clearState(reducer: ActionReducer<StoreStates>): ActionReducer<StoreStates>
return function(state: StoreStates, action: Action): StoreStates
if (action.type === 'CLEAR_STATE')
state = undefined;
return reducer(state, action);
;
export const metaReducers: MetaReducer<StoreStates>[] = [clearState];
和
import StoreModule from '@ngrx/store';
import metaReducers, rootReducer from '../root.reducer';
export const imports: any = [
StoreModule.forRoot(rootReducer, metaReducers ),
...
]
【讨论】:
当应用程序被组织成模块(延迟加载)并且每个模块都有自己的功能状态时,这将如何工作? 它也适用于延迟加载,我的意思是我的所有功能模块都延迟加载,但服务和商店位于我放入应用程序模块的共享模块中 顺便说一句,我的 CLEAR_STATE 操作是 LOGOUT ACTION)【参考方案4】:这不是一个真正的答案,但 cmets 不会让我正确格式化它。补充一下 carant 所说的,如果您要这样设置类型:
export const ActionTypes =
LOGOUT: type('[Environment] Logout of portal'),
....
这是您应该使用的长描述。此外,如果您将根减速器命名为 rootReducer
而不仅仅是 reducer
,那么您也可以更改它。以下是经过编辑的示例:
(我将这个函数留在了我的根减速器中)
const developmentReducer: ActionReducer<State> = compose(...DEV_REDUCERS,
(rootReducer: Function) =>
return function(state, action)
if (action.type === '[Environment] Logout of portal')
state = undefined;
return rootReducer(state, action);
;
, combineReducers)(reducers);
【讨论】:
你如何使用 productionReducer 做到这一点?以上是关于如何重置ngrx/store的所有状态?的主要内容,如果未能解决你的问题,请参考以下文章
Angular 状态管理 - 存储还是有状态服务? [关闭]
在 @ngrx/store 4.0 中提供 root reducer