【问题标题】:How to reset the state of a Redux store?如何重置 Redux 存储的状态?
【发布时间】:2021-07-22 23:40:24
【问题描述】:

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

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

  1. 用户u1 登录到应用程序并执行一些操作,因此我们在存储中缓存了一些数据。

  2. 用户u1 注销。

  3. 用户u2无需刷新浏览器即可登录应用。

此时缓存的数据会关联到u1,我想清理一下。

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

【问题讨论】:

标签: javascript redux store redux-store


【解决方案1】:

一种方法是在您的应用程序中编写一个根减速器。

根减速器通常会将处理操作委托给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 操作。正如我们所知,reducers 应该在以undefined 作为第一个参数调用它们时返回初始状态,无论操作如何。让我们利用这个事实有条件地剥离累积的state,因为我们将它传递给appReducer:

 const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    return appReducer(undefined, action)
  }

  return appReducer(state, action)
}

现在,每当USER_LOGOUT 触发时,所有reducer 都会重新初始化。如果他们愿意,他们也可以返回与最初不同的东西,因为他们也可以检查action.type。

重申一下,完整的新代码如下所示:

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 将您的状态副本保存在存储引擎中,状态副本将在刷新时从那里加载。

首先,您需要导入适当的storage engine,然后在将其设置为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);
};

【讨论】:

  • 我很好奇丹,你能不能在你的减速机中做这样的事情。以 CLEAR_DATA 为动作。 case 'CLEAR_DATA': return initialState
  • @HussienK 可以工作,但不适用于每个减速器的状态。
  • 这是一个动态组合减速器的版本,以防您使用异步减速器:export const createRootReducer = asyncReducers => { const appReducer = combineReducers({ myReducer ...asyncReducers }); return (state, action) => { if (action.type === 'LOGOUT_USER') { state = undefined; } return appReducer(state, action); } };
  • 如果初始状态还包括一些外部数据,例如来自 localStorage 怎么办?
  • 这种方法是否完全清除了状态及其所有历史?我从安全的角度考虑:如果这已经实现,一旦USER_LOGOUT 动作被触发,是否有可能从更早的时候获取状态数据? (例如通过 devtools)
【解决方案2】:

Dan Abramov 的answer 是正确的,只是我们在使用 react-router-redux 包和这种方法时遇到了一个奇怪的问题。

我们的解决方法是不将状态设置为undefined,而是仍然使用当前的路由减速器。因此,如果您正在使用此软件包,我建议您实施以下解决方案

const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    const { routing } = state
    state = { routing } 
  }
  return appReducer(state, action)
}

【讨论】:

  • 我认为这里的要点是您可能不想在注销时清除整个状态树 - 该方法在任何子树的根减速器上都同样适用,因此应用它可能更清晰仅在您确实要清除的子树的根化简器中使用技术,而不是挑选出“特殊”子代不在整个根化简器清除树,像这样
  • 我想我现在遇到了你所指的这个问题,(在注销时它将设置路由到正确的路径,但会加载一个完全不同的组件)我实现了类似于你的东西修复它,但我认为不可变 js 的东西正在堆积起来。我最终创建了一个具有 RESET-STATE 操作的父减速器,并且我从该减速器继承以避免完全接触路由
  • 遇到类似问题,已解决。谢谢。
  • 请注意,对于 react-redux-router,属性是 router 而不是 rounting
  • @Mrchief 这取决于您在combineReducers() 中定义的内容......如果您有combineReducers({routing: routingReducer}),它将如答案中所述
【解决方案3】:

定义一个动作:

const RESET_ACTION = {
  type: "RESET"
}

然后在每个减速器中假设您使用switch 或if-else 通过每个减速器处理多个操作。我要为switch 处理此案。

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.dispatch(RESET_ACTION) 只是阐述了这个想法。为此,您很可能有一个动作创建者。一个更好的方法是你有一个LOGOUT_ACTION。

一旦您发送此LOGOUT_ACTION。然后,自定义中间件可以使用 Redux-Saga 或 Redux-Thunk 拦截此操作。然而,这两种方式,您都可以发送另一个操作“RESET”。这样,商店注销和重置将同步发生,您的商店将为其他用户登录做好准备。

【讨论】:

  • 我觉得这是比在另一个答案中将状态设置为 undefined 更好的方法。当您的应用程序需要状态树并且您将其提供为 undefined 时,除了一棵空树之外,还有更多的错误和令人头疼的问题需要处理。
  • @worc 状态实际上不会是未定义的,因为 reducer 在收到未定义状态时会返回 initialState
  • @worc 认为使用这种方法,每次任何人创建新的 reducer 时,您都必须记住添加重置案例。
  • 我确实改变了主意,这两个原因,加上RESET_ACTION是一个动作的想法。所以它并不真正属于减速器。
  • 这绝对是正确的做法。将状态设置为除初始状态之外的任何内容都是自找麻烦
【解决方案4】:

只是对Dan Abramov 的answer 的简单回答:

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


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

【讨论】:

    【解决方案5】:

    使用 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);
    };
    

    【讨论】:

    • 这个解决方案对我有用,只需少量更改。我需要添加 undefined 作为状态的可选类型,因此它可以与 configureStore "state: ReturnType | undefined" 一起使用
    【解决方案6】:
     const reducer = (state = initialState, { type, payload }) => {
    
       switch (type) {
          case RESET_STORE: {
            state = initialState
          }
            break
       }
    
       return state
     }
    

    您还可以触发由所有或部分减速器处理的操作,您希望将其重置为初始存储。一个动作可以触发对你的整个状态的重置,或者只是一个看起来适合你的状态。我相信这是最简单、最可控的方式。

    【讨论】:

      【解决方案7】:

      从安全角度来看,注销用户时最安全的做法是重置所有持久状态(例如 cookie、localStorage、IndexedDB、Web SQL 等)并硬刷新页面使用window.location.reload()。一个草率的开发人员可能会意外或故意将一些敏感数据存储在window、DOM 等中。清除所有持久状态并刷新浏览器是保证前一个用户的信息不会泄露给下一个用户的唯一方法.

      (当然,作为共享计算机的用户,你应该使用“隐私浏览”模式,自己关闭浏览器窗口,使用“清除浏览数据”功能等,但作为开发者我们不能指望所有人永远那么勤奋)

      【讨论】:

      • 为什么人们不赞成这个?当你做一个新的 redux state 时,内容是空的,你基本上仍然有以前的 state 在内存中,理论上你可以访问它们中的数据。刷新浏览器是您最安全的选择!
      • 谢谢。这就是我所看到的,所有其他答案只是返回一个新状态,而不是按照 OP 的要求重置它
      【解决方案8】:

      如果使用 Redux,如果应用了以下解决方案,假设我在所有减速器中设置了 initialState(例如 { user: { name, email }})。在许多组件中,我检查了这些嵌套属性,因此通过此修复,我可以防止我的渲染方法在耦合属性条件下被破坏(例如,如果state.user.email,如果上面提到的解决方案将引发错误user is undefined)。

      const appReducer = combineReducers({
        tabs,
        user
      })
      
      const initialState = appReducer({}, {})
      
      const rootReducer = (state, action) => {
        if (action.type === 'LOG_OUT') {
          state = initialState
        }
      
        return appReducer(state, action)
      }
      

      【讨论】:

        【解决方案9】:

        更新 NGRX4

        如果您正在迁移到 NGRX 4,您可能已经从 migration guide 注意到用于组合减速器的 rootreducer 方法已被 ActionReducerMap 方法替换。起初,这种新的做事方式可能会使重置状态成为一项挑战。它实际上很简单,但是这样做的方式已经改变了。

        此解决方案的灵感来自 NGRX4 Github docs. 的元减速器 API 部分

        首先,假设您正在使用 NGRX 的新 ActionReducerMap 选项组合您的减速器:

        //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 实现相同效果的一种方法。

        【讨论】:

          【解决方案10】:

          我在使用 typescript 时的解决方法,建立在 Dan Abramov 的 answer 之上(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"})
            }
          }
          

          【讨论】:

            【解决方案11】:

            结合Dan Abramov 的answer、Ryan Irilli 的answer 和Rob Moorman 的answer,以说明保持router 状态并初始化状态树中的所有其他内容,我结果是这样的:

            const rootReducer = (state, action) => appReducer(action.type === LOGOUT ? {
                ...appReducer({}, {}),
                router: state && state.router || {}
              } : state, action);
            

            【讨论】:

              【解决方案12】:

              只需让您的注销链接清除会话并刷新页面。您的商店不需要额外的代码。每当您想完全重置状态时,页面刷新都是一种简单且易于重复的处理方式。

              【讨论】:

              • 如果你使用一个将 store 同步到 localstorage 的中间件呢?那么你的方法根本行不通……
              • 我真的不明白为什么人们会否决这样的答案。
              • 为什么人们不赞成这个?当你做一个新的 redux 状态,内容为空时,你基本上仍然在内存中保留以前的状态,理论上你可以从它们中访问数据。刷新浏览器是您最安全的选择!
              【解决方案13】:

              我已经创建了清除状态的动作。因此,当我分派注销操作创建者时,我也会分派操作以清除状态。

              用户记录操作

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

              我不确定这是否最佳?

              【讨论】:

              • 为什么不在CLEAR_USER_RECORD的情况下直接返回state?
              【解决方案14】:

              如果您使用的是redux-actions,这里有一个快速解决方法,对handleActions 使用 HOF(高阶函数)。

              import { handleActions } from 'redux-actions';
              
              export function handleActionsEx(reducer, initialState) {
                const enhancedReducer = {
                  ...reducer,
                  RESET: () => initialState
                };
                return handleActions(enhancedReducer, initialState);
              }
              

              然后用handleActionsEx代替原来的handleActions来处理reducers。

              Dan's answer 对这个问题提出了一个很好的想法,但对我来说效果不佳,因为我使用的是redux-persist。
              当与redux-persist 一起使用时,简单地传递undefined 状态不会触发持久行为,所以我知道我必须手动从存储中删除项目(在我的例子中是React Native,因此AsyncStorage)。

              await AsyncStorage.removeItem('persist:root');
              

              或

              await persistor.flush(); // or await persistor.purge();
              

              对我也不起作用——他们只是对我大喊大叫。 (例如,像 “Unexpected key _persist ...”之类的抱怨)

              然后我突然想,我只想让每个reducer在遇到RESET动作类型时返回自己的初始状态。这样,持久化就自然而然地处理了。显然,如果没有上述实用程序函数 (handleActionsEx),我的代码看起来不会 DRY(尽管它只是一个单行,即 RESET: () =&gt; initialState),但我无法忍受,因为我喜欢元编程。

              【讨论】:

                【解决方案15】:

                我认为 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;
                  }
                };
                

                【讨论】:

                • 将默认状态写成函数的想法确实节省了一天的时间。谢谢?
                【解决方案16】:

                我已经创建了一个组件来赋予 Redux 重置状态的能力,你只需要使用这个组件来增强你的 store 并发送一个特定的action.type 来触发重置。实现的思路和Dan Abramov在他们的answer里说的一样。

                Github:https://github.com/wwayne/redux-reset

                【讨论】:

                  【解决方案17】:

                  以下解决方案对我有用。

                  我在元减速器中添加了重置状态功能。关键是使用

                  return reducer(undefined, action);
                  

                  将所有减速器设置为初始状态。而是返回 undefined 会导致错误,因为商店的结构已被破坏。

                  /reducers/index.ts

                  export function resetState(reducer: ActionReducer<State>): ActionReducer<State> {
                    return function (state: State, action: Action): State {
                  
                      switch (action.type) {
                        case AuthActionTypes.Logout: {
                          return reducer(undefined, action);
                        }
                        default: {
                          return reducer(state, action);
                        }
                      }
                    };
                  }
                  
                  export const metaReducers: MetaReducer<State>[] = [ resetState ];
                  

                  app.module.ts

                  import { StoreModule } from '@ngrx/store';
                  import { metaReducers, reducers } from './reducers';
                  
                  @NgModule({
                    imports: [
                      StoreModule.forRoot(reducers, { metaReducers })
                    ]
                  })
                  export class AppModule {}
                  

                  【讨论】:

                    【解决方案18】:

                    Dan Abramov 的answer 帮助我解决了我的问题。但是,我遇到了不必清除整个状态的情况。所以我是这样做的:

                    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;
                    

                    【讨论】:

                    • 如果我有超过 10 个状态但我只想重置一个减速器的状态怎么办?
                    【解决方案19】:

                    只是@dan-abramov 答案的扩展,有时我们可能需要保留某些键以免被重置。

                    const retainKeys = ['appConfig'];
                    
                    const rootReducer = (state, action) => {
                      if (action.type === 'LOGOUT_USER_SUCCESS' && state) {
                        state = !isEmpty(retainKeys) ? pick(state, retainKeys) : undefined;
                      }
                    
                      return appReducer(state, action);
                    };
                    

                    【讨论】:

                      【解决方案20】:

                      这种做法非常正确:破坏任何特定状态“NAME”以忽略并保留其他状态。

                      const rootReducer = (state, action) => {
                          if (action.type === 'USER_LOGOUT') {
                              state.NAME = undefined
                          }
                          return appReducer(state, action)
                      }
                      

                      【讨论】:

                      • 如果你只需要重置你的状态树的一部分,你也可以在那个reducer中监听USER_LOGOUT并在那里处理它。
                      【解决方案21】:

                      为了让我将状态重置为初始状态,我编写了以下代码:

                      const appReducers = (state, action) =>
                         combineReducers({ reducer1, reducer2, user })(
                           action.type === "LOGOUT" ? undefined : state,
                           action
                      );
                      

                      【讨论】:

                        【解决方案22】:

                        我发现 Dan Abramov 的 answer 对我很有效,但它触发了 ESLint no-param-reassign 错误 - https://eslint.org/docs/rules/no-param-reassign

                        这是我处理它的方法,确保创建状态的副本(在我的理解中,这就是 Reduxy 要做的事情......):

                        import { combineReducers } from "redux"
                        import { routerReducer } from "react-router-redux"
                        import ws from "reducers/ws"
                        import session from "reducers/session"
                        import app from "reducers/app"
                        
                        const appReducer = combineReducers({
                            "routing": routerReducer,
                            ws,
                            session,
                            app
                        })
                        
                        export default (state, action) => {
                            const stateCopy = action.type === "LOGOUT" ? undefined : { ...state }
                            return appReducer(stateCopy, action)
                        }
                        

                        但是也许创建一个状态的副本只是将它传递给另一个reducer 函数来创建一个副本有点过于复杂?这读起来不太好,但更中肯:

                        export default (state, action) => {
                            return appReducer(action.type === "LOGOUT" ? undefined : state, action)
                        }
                        

                        【讨论】:

                          【解决方案23】:

                          首先在我们的应用程序初始化时,reducer 状态是 fresh 和 new 与默认 InitialState。

                          我们必须添加一个调用 APP 初始加载的操作以保持 默认状态。

                          在退出应用程序时,我们可以简单地重新分配默认状态,reducer 将像新。

                          主应用容器

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

                          【讨论】:

                            【解决方案24】:

                            Dan Abramov 的answer 没有做的一件事是清除参数化选择器的缓存。如果你有这样的选择器:

                            export const selectCounter1 = (state: State) => state.counter1;
                            export const selectCounter2 = (state: State) => state.counter2;
                            export const selectTotal = createSelector(
                              selectCounter1,
                              selectCounter2,
                              (counter1, counter2) => counter1 + counter2
                            );
                            

                            然后你必须像这样在注销时释放它们:

                            selectTotal.release();
                            

                            否则,上次调用选择器的记忆值和最后一个参数的值仍然在内存中。

                            代码示例来自ngrx docs。

                            【讨论】:

                            • 您发布了关于 RxJS 的答案,但 OP 要求使用 Redux。逻辑是一样的。
                            【解决方案25】:

                            使用 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)
                            

                            在您的注销功能中发送您的“重置”

                            store.dispatch({
                                type: 'RESET'
                            })
                            

                            【讨论】:

                              【解决方案26】:

                              使用 Redux 工具包的方法:

                              
                              export const createRootReducer = (history: History) => {
                                const rootReducerFn = combineReducers({
                                  auth: authReducer,
                                  users: usersReducer,
                                  ...allOtherReducers,
                                  router: connectRouter(history),
                                });
                              
                                return (state: Parameters<typeof rootReducerFn>[0], action: Parameters<typeof rootReducerFn>[1]) =>
                                  rootReducerFn(action.type === appActions.reset.type ? undefined : state, action);
                              };
                              
                              

                              【讨论】:

                                【解决方案27】:

                                你为什么不直接使用return module.exports.default() ;)

                                export default (state = {pending: false, error: null}, action = {}) => {
                                    switch (action.type) {
                                        case "RESET_POST":
                                            return module.exports.default();
                                        case "SEND_POST_PENDING":
                                            return {...state, pending: true, error: null};
                                        // ....
                                    }
                                    return state;
                                }
                                

                                注意:确保将操作默认值设置为{},因为您不想在switch语句中检查action.type时遇到错误。

                                【讨论】:

                                  【解决方案28】:

                                  另一种选择是:

                                  store.dispatch({type: '@@redux/INIT'})
                                  

                                  '@@redux/INIT' 是当你 createStore 时 redux 自动调度的动作类型,所以假设你的 reducer 都已经有一个默认值,这会被它们捕获并重新开始你的 state。不过,它可能被认为是 redux 的私有实现细节,所以买家要小心......

                                  【讨论】:

                                  • 我做到了它没有改变状态,我也尝试了@@INIT,它在 ReduxDevtools 中显示为第一个操作
                                  【解决方案29】:

                                  对我来说,最好的方法是设置initialState 而不是state:

                                    const reducer = createReducer(initialState,
                                    on(proofActions.cleanAdditionalInsuredState, (state, action) => ({
                                      ...initialState
                                    })),
                                  

                                  【讨论】:

                                    【解决方案30】:

                                    如果你想重置单个reducer

                                    例如

                                    const initialState = {
                                      isLogged: false
                                    }
                                    //this will be your action
                                    export const resetReducer = () => {
                                      return {
                                        type: "RESET"
                                      }
                                    }
                                    
                                    export default (state = initialState, {
                                      type,
                                      payload
                                    }) => {
                                      switch (type) {
                                        //your actions will come her
                                        case "RESET":
                                          return {
                                            ...initialState
                                          }
                                      }
                                    }
                                    
                                    //and from your frontend
                                    dispatch(resetReducer())

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2016-06-07
                                      • 1970-01-01
                                      • 2016-07-10
                                      • 2018-05-03
                                      • 1970-01-01
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多