我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
当前回答
为了将状态重置为初始状态,我编写了以下代码:
const appReducers = (state, action) =>
combineReducers({ reducer1, reducer2, user })(
action.type === "LOGOUT" ? undefined : state,
action
);
其他回答
如果你正在使用还原动作,这里有一个快速的解决方案,使用HOF(高阶函数)为handleActions。
import { handleActions } from 'redux-actions';
export function handleActionsEx(reducer, initialState) {
const enhancedReducer = {
...reducer,
RESET: () => initialState
};
return handleActions(enhancedReducer, initialState);
}
然后使用handleActionsEx代替原来的handleActions来处理reducers。
Dan的回答给出了关于这个问题的一个很好的想法,但它对我来说并不是很有效,因为我使用的是还原坚持。 当使用redux-persist时,简单地传递未定义的状态不会触发持久化行为,所以我知道我必须手动从存储中删除项目(在我的情况下,React Native,因此AsyncStorage)。
await AsyncStorage.removeItem('persist:root');
or
await persistor.flush(); // or await persistor.purge();
对我也没用——他们只是对我大喊大叫。(例如,抱怨“意外的键_persist…”)
然后我突然思考,我想要的只是让每个减速机在遇到RESET动作类型时回到自己的初始状态。这样,持久化就被自然地处理了。显然没有上面的实用函数(handleActionsEx),我的代码不会看起来很干(虽然它只是一个一行程序,即RESET: () => initialState),但我不能容忍它,因为我喜欢元编程。
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达到同样效果的一种方法。
在服务器中,有一个变量:global。isSsr = true 在每个reducer中,我都有一个const: initialState 要重置存储中的数据,我对每个Reducer执行以下操作:
appReducer.js的例子:
const initialState = {
auth: {},
theme: {},
sidebar: {},
lsFanpage: {},
lsChatApp: {},
appSelected: {},
};
export default function (state = initialState, action) {
if (typeof isSsr!=="undefined" && isSsr) { //<== using global.isSsr = true
state = {...initialState};//<= important "will reset the data every time there is a request from the client to the server"
}
switch (action.type) {
//...other code case here
default: {
return state;
}
}
}
最后在服务器的路由器上:
router.get('*', (req, res) => {
store.dispatch({type:'reset-all-blabla'});//<= unlike any action.type // i use Math.random()
// code ....render ssr here
});
只是对@dan-abramov答案的扩展,有时我们可能需要保留某些被重置的键。
const retainKeys = ['appConfig'];
const rootReducer = (state, action) => {
if (action.type === 'LOGOUT_USER_SUCCESS' && state) {
state = !isEmpty(retainKeys) ? pick(state, retainKeys) : undefined;
}
return appReducer(state, action);
};
结合Dan Abramov的回答,Ryan Irilli的回答和Rob Moorman的回答,来解释保持路由器状态和初始化状态树中的其他所有东西,我最终得到了这样的答案:
const rootReducer = (state, action) => appReducer(action.type === LOGOUT ? {
...appReducer({}, {}),
router: state && state.router || {}
} : state, action);