我正在使用Angular 2和1。我想在用户发送USER_LOGOUT
时重置整个商店状态。
我读了Dan Abramov对ngrx/store的回答,但我没有弄清楚如何正确地写rootReducer
以及在使用ngrx / store时把它放在哪里。
或者还有其他方法可以在ngrx / store中处理这个吗?
bootstrap(App, [
provideStore(
compose(
storeFreeze,
storeLogger(),
combineReducers
)({
router: routerReducer,
foo: fooReducer,
bar: barReducer
})
)
]);
答案 0 :(得分:32)
在ngrx / store 4.x中,可以使用metareducers完成此操作。据我了解,所有操作都会在传递给功能减少器之前通过元数据删除器。这使我们有机会首先更改/重置状态。
以下是一个例子。
这是我的metareducer函数:如果操作是LOGOUT类型,则重新初始化状态。
function logout(reducer) {
return function (state, action) {
return reducer(action.type === LOGOUT ? undefined : state, action);
}
}
下面您将看到如何配置metareducer以及功能缩减器。如果有超过1个metareducer,那么它们将从右到左进行评估
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'])
});
答案 1 :(得分:14)
此答案特定于ngrx版本2.问题为another, more recent answer,解释了如何使用ngrx版本4完成相同的操作。
<!--------------------------- EXTERNAL BOILER PLATE STUFF -----------------------------> <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script><link rel="stylesheet" type="text/css" href="/css/result-light.css"><link rel="stylesheet" type="text/css" href="http://getbootstrap.com/2.3.2/assets/css/bootstrap.css"><link rel="stylesheet" type="text/css" href="http://getbootstrap.com/2.3.2/assets/css/bootstrap-responsive.css"><link rel="stylesheet" type="text/css" href="http://jschr.github.io/bootstrap-modal/css/bootstrap-modal.css"><script type="text/javascript" src="http://getbootstrap.com/2.3.2/assets/js/bootstrap.js"></script><script type="text/javascript" src="http://jschr.github.io/bootstrap-modal/js/bootstrap-modalmanager.js"></script><script type="text/javascript" src="http://jschr.github.io/bootstrap-modal/js/bootstrap-modal.js"></script>
<a id="newBtn" href="#" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">New</a>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="exampleModalLabel">Input parameters</h4>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="url-base" class="form-control-label">Base URL (optional):</label>
<input type="text" class="form-control" id="url-base" placeholder="Example: https://www.merkel.com/obama?trump=15&id=9616071454&hilarry=es">
</div>
<div class="form-group">
<label for="max-pics" class="form-control-label">Max #pics:</label>
<input type="text" class="form-control" id="max-pics" placeholder="Default: 7">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button id="paramsOkay" type="button" class="btn btn-primary">Okay</button>
</div>
</div>
</div>
</div>
构建ngrx 根减速器。
传递给compose
的参数是返回reducer的函数 - 由reducer组成,它们本身作为参数传递。您可以像这样构建商店的重置:
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
})
)
]);
。如果那不是你想要的,你可以调整一下这个例子。
引入router
引导已更改,但您仍然将组合的reducer传递给NgModule
:
provideStore
答案 2 :(得分:13)
使用@ ngrx / store&#34;:&#34; ^ 4.0.3&#34;这略有不同,因为有一些小的变化,所以我的状态很明显&#39;看起来像这样
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 }),
...
]
答案 3 :(得分:2)
这不是一个真正的答案,但评论不会让我正确格式化。要添加到cartant所说的内容,如果您要设置类似的类型:
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);
,那么您也可以更改它。以下是一个经过编辑的例子:
(我在root减速器中保留了这个功能)
static public charchar box1 = ' ', box2 = ' ', box3 = ' ', box4 = ' ', box5 = ' ', box6 = ' ', box7 = ' ', box8 = ' ', box9 = ' ', input2;
static public void reset()
{
char box1 = ' ', box2 = ' ', box3 = ' ', box4 = ' ', box5 = ' ', box6 = ' ', box7 = ' ', box8 = ' ', box9 = ' ', input2;
bool isWin = false;
int line = 1, nrJogada = 1;
ciclo();
}