我正在使用Redux进行状态管理。 如何将存储重置为初始状态?

例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:

用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。

此时,缓存的数据将与u1关联,我想清理它。

当第一个用户注销时,如何将Redux存储重置为初始状态?


当前回答

你可以通过将此代码添加到动作文件中来清空减速器的数据,

首先导入所有类型:

import * as types from './types';

将此代码添加到注销操作

for(let key of Object.values(types)) {
        dispatch({ type: key, payload: [] });
    }

其他回答

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

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


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

定义一个动作:

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引用初始状态的相同变量,我的建议是:

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

在服务器中,有一个变量: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
});

NGRX4更新

如果您正在迁移到NGRX 4,您可能已经从迁移指南中注意到用于组合reducer的rootreducer方法已经被ActionReducerMap方法所取代。起初,这种新的做事方式可能会使重置状态成为一个挑战。它实际上很简单,但这样做的方式已经改变了。

这个解决方案的灵感来自NGRX4 Github文档的元还原器API部分。

首先,让我们假设你正在使用NGRX的新ActionReducerMap选项像这样组合你的reducer:

//index.reducer.ts
export const reducers: ActionReducerMap<State> = {
    auth: fromAuth.reducer,
    layout: fromLayout.reducer,
    users: fromUsers.reducer,
    networks: fromNetworks.reducer,
    routingDisplay: fromRoutingDisplay.reducer,
    routing: fromRouting.reducer,
    routes: fromRoutes.reducer,
    routesFilter: fromRoutesFilter.reducer,
    params: fromParams.reducer
}

现在,假设你想从app。module内部重置状态

//app.module.ts
import { IndexReducer } from './index.reducer';
import { StoreModule, ActionReducer, MetaReducer } from '@ngrx/store';
...
export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
    return function(state, action) {

      switch (action.type) {
          case fromAuth.LOGOUT:
            console.log("logout action");
            state = undefined;
      }
  
      return reducer(state, action);
    }
  }

  export const metaReducers: MetaReducer<any>[] = [debug];

  @NgModule({
    imports: [
        ...
        StoreModule.forRoot(reducers, { metaReducers}),
        ...
    ]
})

export class AppModule { }

这基本上是用NGRX 4达到同样效果的一种方法。