我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
当前回答
我在使用typescript时的解决方案,建立在Dan Abramov的答案之上(redux类型使得不可能将undefined作为第一个参数传递给reducer,所以我将初始根状态缓存在一个常量中):
// store
export const store: Store<IStoreState> = createStore(
rootReducer,
storeEnhacer,
)
export const initialRootState = {
...store.getState(),
}
// root reducer
const appReducer = combineReducers<IStoreState>(reducers)
export const rootReducer = (state: IStoreState, action: IAction<any>) => {
if (action.type === "USER_LOGOUT") {
return appReducer(initialRootState, action)
}
return appReducer(state, action)
}
// auth service
class Auth {
...
logout() {
store.dispatch({type: "USER_LOGOUT"})
}
}
其他回答
简单回答一下丹·阿布拉莫夫的问题:
const rootReducer = combineReducers({
auth: authReducer,
...formReducers,
routing
});
export default (state, action) =>
rootReducer(action.type === 'USER_LOGOUT' ? undefined : state, action);
只需将注销链接清除会话并刷新页面。您的商店不需要额外的代码。当您想要完全重置状态时,页面刷新是一种简单且易于重复的处理方法。
NGRX4更新
如果您正在迁移到NGRX 4,您可能已经从迁移指南中注意到用于组合reducer的rootreducer方法已经被ActionReducerMap方法所取代。起初,这种新的做事方式可能会使重置状态成为一个挑战。它实际上很简单,但这样做的方式已经改变了。
这个解决方案的灵感来自NGRX4 Github文档的元还原器API部分。
首先,让我们假设你正在使用NGRX的新ActionReducerMap选项像这样组合你的reducer:
//index.reducer.ts
export const reducers: ActionReducerMap<State> = {
auth: fromAuth.reducer,
layout: fromLayout.reducer,
users: fromUsers.reducer,
networks: fromNetworks.reducer,
routingDisplay: fromRoutingDisplay.reducer,
routing: fromRouting.reducer,
routes: fromRoutes.reducer,
routesFilter: fromRoutesFilter.reducer,
params: fromParams.reducer
}
现在,假设你想从app。module内部重置状态
//app.module.ts
import { IndexReducer } from './index.reducer';
import { StoreModule, ActionReducer, MetaReducer } from '@ngrx/store';
...
export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
return function(state, action) {
switch (action.type) {
case fromAuth.LOGOUT:
console.log("logout action");
state = undefined;
}
return reducer(state, action);
}
}
export const metaReducers: MetaReducer<any>[] = [debug];
@NgModule({
imports: [
...
StoreModule.forRoot(reducers, { metaReducers}),
...
]
})
export class AppModule { }
这基本上是用NGRX 4达到同样效果的一种方法。
我在使用typescript时的解决方案,建立在Dan Abramov的答案之上(redux类型使得不可能将undefined作为第一个参数传递给reducer,所以我将初始根状态缓存在一个常量中):
// store
export const store: Store<IStoreState> = createStore(
rootReducer,
storeEnhacer,
)
export const initialRootState = {
...store.getState(),
}
// root reducer
const appReducer = combineReducers<IStoreState>(reducers)
export const rootReducer = (state: IStoreState, action: IAction<any>) => {
if (action.type === "USER_LOGOUT") {
return appReducer(initialRootState, action)
}
return appReducer(state, action)
}
// auth service
class Auth {
...
logout() {
store.dispatch({type: "USER_LOGOUT"})
}
}
除了Dan Abramov的回答之外,我们是否应该明确地将action设置为action = {type: '@@INIT'}以及state = undefined。采用上述动作方式,各减速器均返回初始状态。