我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
我正在使用Redux进行状态管理。 如何将存储重置为初始状态?
例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:
用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。
此时,缓存的数据将与u1关联,我想清理它。
当第一个用户注销时,如何将Redux存储重置为初始状态?
当前回答
只需编辑声明约简的文件
import { combineReducers } from 'redux';
import gets from '../';
const rootReducer = (state, action) => {
let asReset = action.type === 'RESET_STORE';
const reducers = combineReducers({
gets,
});
const transition = {
true() {
return reducers({}, action);
},
false() {
return reducers(state, action);
},
};
return transition[asReset] && transition[asReset]();
};
export default rootReducer;
其他回答
在服务器中,有一个变量: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
});
一种方法是在应用程序中编写一个根减速器。
根减速机通常会将处理操作委托给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);
};
丹·阿布拉莫夫的回答帮我破案了。然而,我遇到了一个案例,并不是整个州都需要清理。所以我是这样做的:
const combinedReducer = combineReducers({
// my reducers
});
const rootReducer = (state, action) => {
if (action.type === RESET_REDUX_STATE) {
// clear everything but keep the stuff we want to be preserved ..
delete state.something;
delete state.anotherThing;
}
return combinedReducer(state, action);
}
export default rootReducer;
只需将注销链接清除会话并刷新页面。您的商店不需要额外的代码。当您想要完全重置状态时,页面刷新是一种简单且易于重复的处理方法。
我在使用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"})
}
}