typescript 如何重置 ngrx/store 的所有状态?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39323285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to reset all states of ngrx/store?
提问by Hongbo Miao
I am using Angular 2 with ngrx/store. I want to reset the whole store states when user dispatch USER_LOGOUT
.
我将 Angular 2 与ngrx/store 一起使用。我想在用户调度时重置整个商店状态USER_LOGOUT
。
I read the Dan Abramov's answer of How to reset the state of a Redux store?, but I didn't figure out how to write rootReducer
correctly and where to put it when using ngrx/store.
我阅读了 Dan Abramov 对如何重置 Redux 商店状态的回答?,但我没有弄清楚rootReducer
在使用 ngrx/store 时如何正确编写以及将它放在哪里。
Or is there any other way to handle this in ngrx/store?
或者有没有其他方法可以在 ngrx/store 中处理这个问题?
bootstrap(App, [
provideStore(
compose(
storeFreeze,
storeLogger(),
combineReducers
)({
router: routerReducer,
foo: fooReducer,
bar: barReducer
})
)
]);
采纳答案by cartant
This answer is specific to ngrx version 2. The question has another, more recent answerthat explains how the same can be done with ngrx version 4.
此答案特定于 ngrx 版本 2。该问题有另一个更新的答案,解释了如何使用 ngrx 版本 4 完成相同的操作。
compose
builds the ngrx root reducer.
compose
构建 ngrx root reducer。
The arguments passed to compose
are functions that return a reducer - composed from the reducer they themselves are passed as an argument. You can compose the resetting of your store like this:
传递给的参数compose
是返回减速器的函数 - 由减速器组成,它们本身作为参数传递。您可以像这样编写商店的重置:
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
})
)
]);
Note that this will reset all of the store's state - including the router
. If that's not what you want, you could tweak the example.
请注意,这将重置商店的所有状态 - 包括router
. 如果这不是您想要的,您可以调整示例。
With introduction of NgModule
the bootstrapping has changed, but you still pass the composed reducer to provideStore
:
随着NgModule
bootstrapping 的引入发生了变化,但您仍然将组合的 reducer 传递给provideStore
:
import { compose } from "@ngrx/core/compose";
import { StoreModule } from "@ngrx/store";
@NgModule({
...
imports: [
...
StoreModule.provideStore(compose(...))
],
...
回答by David Bulté
In ngrx/store 4.x, this can be accomplished with metareducers. As I understand it, all actions are passing through the metareducers before being handed over to the feature reducers. This gives us the opportunity to change/reset the state first.
在 ngrx/store 4.x 中,这可以通过metareducers来完成。据我了解,所有操作都经过元减速器,然后才移交给功能减速器。这使我们有机会首先更改/重置状态。
Here's an example.
这是一个例子。
This is my metareducer function: in case the action is of type LOGOUT, the state is re-initialized.
这是我的 metareducer 函数:如果操作是 LOGOUT 类型,则重新初始化状态。
function logout(reducer) {
return function (state, action) {
return reducer(action.type === LOGOUT ? undefined : state, action);
}
}
Below you see how the metareducer is configured along with the feature reducers. Should there be more than 1 metareducer, then they are evaluated from right to left
下面您将看到元减速器是如何与特征减速器一起配置的。如果有超过 1 个 metareducer,则从右到左评估它们
StoreModule.forRoot({rooms: roomReducer, user: userReducer}, {metaReducers: [logout]})
Finally, I also have an @effect where I navigate to the login page
最后,我还有一个 @effect 我导航到登录页面
@Effect({dispatch: false}) logout: Observable<Action> =
this.actions$.ofType(LOGOUT)
.do(() => {
// ... some more stuff here ...
this.router.navigate(['/login page'])
});
回答by Limarenko Denis
With @ngrx/store": "^4.0.3" this is slightly different because there are small changes, so my 'clear state' looks like this
使用@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];
and
和
import { StoreModule } from '@ngrx/store';
import { metaReducers, rootReducer } from '../root.reducer';
export const imports: any = [
StoreModule.forRoot(rootReducer, { metaReducers }),
...
]
回答by Helzgate
This isn't really an answer but the comments won't let me format it correctly. To add to what cartant said, if you are setting up your types like this:
这不是真正的答案,但评论不会让我正确格式化。添加到 carant 所说的内容,如果您像这样设置您的类型:
export const ActionTypes = {
LOGOUT: type('[Environment] Logout of portal'),
....
}
It's the long description that you should use. Also if you name your root reducer rootReducer
instead of just reducer
then you would change that as well. Following is an edited example:
这是您应该使用的长描述。此外,如果您命名您的根减速器rootReducer
而不是仅命名reducer
那么您也会更改它。以下是经过编辑的示例:
(I left this function within my root 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);