我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
当前回答
npm install redux-reset
import reduxReset from 'redux-reset'
...
const enHanceCreateStore = compose(
applyMiddleware(...),
reduxReset() // Will use 'RESET' as default action.type to trigger reset
)(createStore)
const store = enHanceCreateStore(reducers)
https://github.com/wwayne/redux-reset
其他回答
除了Dan Abramov的回答之外,我们是否应该明确地将action设置为action = {type: '@@INIT'}以及state = undefined。采用上述动作方式,各减速器均返回初始状态。
Dan Abramov的答案是正确的,除了我们在使用react-router-redux包时遇到了一个奇怪的问题。
我们的解决方案是不将状态设置为undefined,而是仍然使用当前的路由减速器。因此,如果您正在使用这个包,我建议实现下面的解决方案
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
const { routing } = state
state = { routing }
}
return appReducer(state, action)
}
首先,在应用程序启动时,减速机的状态是新鲜的,并带有默认的InitialState。
我们必须添加一个动作,调用APP初始加载持续默认状态。
当注销应用程序时,我们可以简单地重新分配默认状态,reducer将像新的一样工作。
APP主容器
componentDidMount() {
this.props.persistReducerState();
}
主APP减速器
const appReducer = combineReducers({
user: userStatusReducer,
analysis: analysisReducer,
incentives: incentivesReducer
});
let defaultState = null;
export default (state, action) => {
switch (action.type) {
case appActions.ON_APP_LOAD:
defaultState = defaultState || state;
break;
case userLoginActions.USER_LOGOUT:
state = defaultState;
return state;
default:
break;
}
return appReducer(state, action);
};
注销时调用重置状态的动作
function* logoutUser(action) {
try {
const response = yield call(UserLoginService.logout);
yield put(LoginActions.logoutSuccess());
} catch (error) {
toast.error(error.message, {
position: toast.POSITION.TOP_RIGHT
});
}
}
定义一个动作:
const RESET_ACTION = {
type: "RESET"
}
然后在每个减速器中假设您使用switch或if-else通过每个减速器处理多个动作。我要拿开关的箱子。
const INITIAL_STATE = {
loggedIn: true
}
const randomReducer = (state=INITIAL_STATE, action) {
switch(action.type) {
case 'SOME_ACTION_TYPE':
//do something with it
case "RESET":
return INITIAL_STATE; //Always return the initial state
default:
return state;
}
}
这样当你调用RESET动作时,你的reducer就会用默认状态更新存储。
现在,注销,你可以处理如下:
const logoutHandler = () => {
store.dispatch(RESET_ACTION)
// Also the custom logic like for the rest of the logout handler
}
每次用户登录时,不需要刷新浏览器。Store将始终处于默认状态。
store.dispatch(RESET_ACTION)只是详细阐述了这个思想。你很可能会有一个用于此目的的动作创建者。更好的方法是使用LOGOUT_ACTION。
一旦分派了这个LOGOUT_ACTION。然后,一个自定义中间件可以用Redux-Saga或Redux-Thunk拦截这个动作。然而,这两种方法都可以分派另一个动作“RESET”。通过这种方式,存储注销和重置将同步发生,您的存储将为另一个用户登录做好准备。
一种方法是在应用程序中编写一个根减速器。
根减速机通常会将处理操作委托给combineReducers()生成的减速机。但是,无论何时它接收到USER_LOGOUT操作,它都会再次返回初始状态。
例如,如果你的根减速器是这样的:
const rootReducer = combineReducers({
/* your app’s top-level reducers */
})
你可以将它重命名为appReducer,并编写一个新的rootReducer委托给它:
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
return appReducer(state, action)
}
现在我们只需要教新的rootReducer返回初始状态以响应USER_LOGOUT操作。如我们所知,无论操作如何,当调用以undefined作为第一个参数时,约简器都应该返回初始状态。让我们用这个事实来有条件地剥离累积状态,当我们把它传递给appReducer:
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
return appReducer(undefined, action)
}
return appReducer(state, action)
}
现在,每当USER_LOGOUT触发时,所有减约器都将重新初始化。它们还可以返回与初始值不同的值,因为它们可以检查动作。也要打字。
重申一下,完整的新代码是这样的:
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
return appReducer(undefined, action)
}
return appReducer(state, action)
}
如果使用redux-persist,可能还需要清理存储空间。Redux-persist将您的状态副本保存在存储引擎中,刷新时将从那里加载状态副本。
首先,您需要导入适当的存储引擎,然后在将其设置为undefined并清除每个存储状态键之前解析状态。
const rootReducer = (state, action) => {
if (action.type === SIGNOUT_REQUEST) {
// for all keys defined in your persistConfig(s)
storage.removeItem('persist:root')
// storage.removeItem('persist:otherKey')
return appReducer(undefined, action);
}
return appReducer(state, action);
};