我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
当前回答
定义一个动作:
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”。通过这种方式,存储注销和重置将同步发生,您的存储将为另一个用户登录做好准备。
其他回答
使用Redux Toolkit和/或Typescript:
const appReducer = combineReducers({
/* your app’s top-level reducers */
});
const rootReducer = (
state: ReturnType<typeof appReducer>,
action: AnyAction
) => {
/* if you are using RTK, you can import your action and use it's type property instead of the literal definition of the action */
if (action.type === logout.type) {
return appReducer(undefined, { type: undefined });
}
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
});
}
}
我已经创建了清除状态的操作。因此,当我分派登出动作创建者时,我也分派动作来清除状态。
用户记录动作
export const clearUserRecord = () => ({
type: CLEAR_USER_RECORD
});
注销操作创建器
export const logoutUser = () => {
return dispatch => {
dispatch(requestLogout())
dispatch(receiveLogout())
localStorage.removeItem('auth_token')
dispatch({ type: 'CLEAR_USER_RECORD' })
}
};
减速机
const userRecords = (state = {isFetching: false,
userRecord: [], message: ''}, action) => {
switch (action.type) {
case REQUEST_USER_RECORD:
return { ...state,
isFetching: true}
case RECEIVE_USER_RECORD:
return { ...state,
isFetching: false,
userRecord: action.user_record}
case USER_RECORD_ERROR:
return { ...state,
isFetching: false,
message: action.message}
case CLEAR_USER_RECORD:
return {...state,
isFetching: false,
message: '',
userRecord: []}
default:
return state
}
};
我不确定这是否是最佳的?
另一种选择是:
store.dispatch({type: '@@redux/INIT'})
'@@redux/INIT'是redux自动调度的动作类型,当你创建存储时,所以假设你的reducers都有一个默认值,这将被那些捕获,并开始你的状态新鲜。不过,它可能被认为是redux的私有实现细节,所以买家要小心……
在服务器中,有一个变量: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
});