注销时重置 redux 状态
Resetting redux state on logout
我正在尝试处理这个问题,通常在较早的线程中解决 - - 需要 reinitialize/invalidate 在用户注销时整个 redux 存储。
然而,就我而言,仍然缺少一些东西。我将 Redux 与 ConnectedRouter 一起使用,并尝试执行以下操作。
将 rootReducer 定义为:
export default history =>
combineReducers({
router: connectRouter(history),
user,
manager,
vendor
// rest of your reducers
});
然后我做 configureStore
,将上面的导入为 createRootReducer
:
const configureStore = (initialState = {}, history) => {
let composeEnhancers = compose;
const composeWithDevToolsExtension =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
const enhancers = [];
const middleware = [sagaMiddleware, thunk, routerMiddleware(history)];
if (typeof composeWithDevToolsExtension === 'function') {
composeEnhancers = composeWithDevToolsExtension;
}
const store = createStore(
createRootReducer(history), // root reducer with router state
initialState,
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
);
store.runSaga = sagaMiddleware.run;
store.subscribe(() => {
const state = store.getState();
const { session } = state['user'];
if (!session) {
console.log('no valid session');
initialState = undefined;
} else {
const { token } = session;
const decodedToken = jwt_decode(token);
const { exp } = decodedToken;
const now = new Date();
if (exp > now.getTime()) {
console.warn('token expired');
initialState = undefined;
} else {
console.log('token valid');
}
}
});
return store;
};
export default configureStore({}, history);
想法是 initialState = undefined;
应该重置我的状态。不过它对我不起作用。
考虑到我正在使用 ConnectedRouter
并将 history
对象传递给它,哪里是执行此操作的正确位置?
在我给你解决方案之前,我想指出一些非常重要的事情:
当使用 redux 时,你不应该试图直接改变你的商店的状态。作为对动作的反应,状态应该始终通过减速器改变。因此,在 subscribe
回调中重新分配参数 initialState
是不正确且毫无意义的。
我不认为你想要 "reset" router
属性 的状态,对吗?
解决此问题的一种方法是使用减速器增强器,如下所示:
const resetEnhancer = rootReducer => (state, action) => {
if (action.type !== 'RESET') return rootReducer(state, action);
const newState = rootReducer(undefined, {});
newState.router = state.router;
return newState;
};
然后在创建商店时执行以下操作:
const store = createStore(
resetEnhancer(createRootReducer(history)),
initialState,
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
);
然后在 subscribe
回调中执行此操作:
if (!session) {
store.dispatch({type: 'RESET'});
}
最后一个额外提示:由于您正在使用 redux-saga
,我强烈建议您将正在做的事情移到 subscribe
回调中。
您可以执行清除商店的操作并在您的 rootReducer
中使用它,如下所示:
const appReducer = combineReducers({
... // your reducers
});
const rootReducer = (state, action) => {
if (action.type === 'CLEAR_STORE') return appReducer(undefined, action);
return appReducer(state, action);
};
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export const configureStore = (initialState, history) =>
createStore(
connectRouter(history)(rootReducer),
initialState,
composeEnhancers(applyMiddleware(routerMiddleware(history), thunkMiddleware))
);
你的所有 reducer 都会有 appReducer
,还有 rootReducer
这将是确定返回相应值或未定义值的函数。
TIP: You can use your Logout action rather than using a new action just for clearing the store
我正在尝试处理这个问题,通常在较早的线程中解决 -
然而,就我而言,仍然缺少一些东西。我将 Redux 与 ConnectedRouter 一起使用,并尝试执行以下操作。
将 rootReducer 定义为:
export default history =>
combineReducers({
router: connectRouter(history),
user,
manager,
vendor
// rest of your reducers
});
然后我做 configureStore
,将上面的导入为 createRootReducer
:
const configureStore = (initialState = {}, history) => {
let composeEnhancers = compose;
const composeWithDevToolsExtension =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
const enhancers = [];
const middleware = [sagaMiddleware, thunk, routerMiddleware(history)];
if (typeof composeWithDevToolsExtension === 'function') {
composeEnhancers = composeWithDevToolsExtension;
}
const store = createStore(
createRootReducer(history), // root reducer with router state
initialState,
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
);
store.runSaga = sagaMiddleware.run;
store.subscribe(() => {
const state = store.getState();
const { session } = state['user'];
if (!session) {
console.log('no valid session');
initialState = undefined;
} else {
const { token } = session;
const decodedToken = jwt_decode(token);
const { exp } = decodedToken;
const now = new Date();
if (exp > now.getTime()) {
console.warn('token expired');
initialState = undefined;
} else {
console.log('token valid');
}
}
});
return store;
};
export default configureStore({}, history);
想法是 initialState = undefined;
应该重置我的状态。不过它对我不起作用。
考虑到我正在使用 ConnectedRouter
并将 history
对象传递给它,哪里是执行此操作的正确位置?
在我给你解决方案之前,我想指出一些非常重要的事情:
当使用 redux 时,你不应该试图直接改变你的商店的状态。作为对动作的反应,状态应该始终通过减速器改变。因此,在
subscribe
回调中重新分配参数initialState
是不正确且毫无意义的。我不认为你想要 "reset"
router
属性 的状态,对吗?
解决此问题的一种方法是使用减速器增强器,如下所示:
const resetEnhancer = rootReducer => (state, action) => {
if (action.type !== 'RESET') return rootReducer(state, action);
const newState = rootReducer(undefined, {});
newState.router = state.router;
return newState;
};
然后在创建商店时执行以下操作:
const store = createStore(
resetEnhancer(createRootReducer(history)),
initialState,
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
);
然后在 subscribe
回调中执行此操作:
if (!session) {
store.dispatch({type: 'RESET'});
}
最后一个额外提示:由于您正在使用 redux-saga
,我强烈建议您将正在做的事情移到 subscribe
回调中。
您可以执行清除商店的操作并在您的 rootReducer
中使用它,如下所示:
const appReducer = combineReducers({
... // your reducers
});
const rootReducer = (state, action) => {
if (action.type === 'CLEAR_STORE') return appReducer(undefined, action);
return appReducer(state, action);
};
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export const configureStore = (initialState, history) =>
createStore(
connectRouter(history)(rootReducer),
initialState,
composeEnhancers(applyMiddleware(routerMiddleware(history), thunkMiddleware))
);
你的所有 reducer 都会有 appReducer
,还有 rootReducer
这将是确定返回相应值或未定义值的函数。
TIP: You can use your Logout action rather than using a new action just for clearing the store