我正在使用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”。通过这种方式,存储注销和重置将同步发生,您的存储将为另一个用户登录做好准备。

其他回答

如果你正在使用还原动作,这里有一个快速的解决方案,使用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),但我不能容忍它,因为我喜欢元编程。

简单回答一下丹·阿布拉莫夫的问题:

const rootReducer = combineReducers({
    auth: authReducer,
    ...formReducers,
    routing
});


export default (state, action) =>
  rootReducer(action.type === 'USER_LOGOUT' ? undefined : state, action);

我已经创建了清除状态的操作。因此,当我分派登出动作创建者时,我也分派动作来清除状态。

用户记录动作

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
  }
};

我不确定这是否是最佳的?

为了避免Redux引用初始状态的相同变量,我的建议是:

// write the default state as a function
const defaultOptionsState = () => ({
  option1: '',
  option2: 42,
});

const initialState = {
  options: defaultOptionsState() // invoke it in your initial state
};

export default (state = initialState, action) => {

  switch (action.type) {

    case RESET_OPTIONS:
    return {
      ...state,
      options: defaultOptionsState() // invoke the default function to reset this part of the state
    };

    default:
    return state;
  }
};

如果你想重置一个减速机

例如

const initialState = { isLogged:假 } //这将是你的行动 export const resetReducer = () => { 返回{ 类型:“重置” } } 导出默认值(state = initialState, { 类型, 有效载荷 }) => { 开关(类型){ //你的行动会报应到她头上 例“重置”: 返回{ initialState… } } } //从你的前端 调度(resetReducer ())