Как сбросить состояние магазина Redux?

455

Я использую Redux для управления состоянием.
Как мне сбросить магазин в исходное состояние?

Например, допустим, у меня есть две учетные записи ( u1и u2).
Представьте себе следующую последовательность событий:

  1. Пользователь u1входит в приложение и что-то делает, поэтому мы кешируем некоторые данные в магазине.

  2. Пользователь u1выходит из системы.

  3. Пользователь u2входит в приложение без обновления браузера.

На этом этапе кэшированные данные будут связаны u1, и я бы хотел их очистить.

Как я могу сбросить хранилище Redux в исходное состояние, когда первый пользователь выходит из системы?

хуг
источник
8
Возможно, лучше очистить состояние при выходе из системы (с точки зрения безопасности)
Кларки,

Ответы:

1033

Один из способов сделать это - написать корневой редуктор в вашем приложении.

Корневой редуктор обычно делегирует обработку действия редуктору, сгенерированному с помощью 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в качестве первого аргумента, независимо от действия. Давайте использовать этот факт для условного удаления накопленного stateпри передаче appReducer:

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

  return appReducer(state, action)
}

Теперь при каждом USER_LOGOUTзапуске все редукторы будут инициализироваться заново. Они также могут вернуть что-то отличное от первоначального, если захотят, потому что они тоже могут проверить action.type.

Повторюсь, полный новый код выглядит так:

const appReducer = combineReducers({
  /* your app’s top-level reducers */
})

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

  return appReducer(state, action)
}

Обратите внимание, что я не изменяю здесь состояние, я просто переназначаю ссылку на локальную переменную, вызываемую stateперед передачей ее другой функции. Мутирование состояния объекта было бы нарушением принципов Redux.

В случае, если вы используете 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')

        state = undefined;
    }
    return appReducer(state, action);
};
Дан Абрамов
источник
15
Мне любопытно, Дэн, не могли бы вы сделать что-то подобное в своем редукторе. с CLEAR_DATA, являющимся действием. case 'CLEAR_DATA': return initialState
HussienK
6
@HussienK, который будет работать, но не на состояние для каждого редуктора.
Кори Дэниелсон
12
Вот версия, в которой вы динамически комбинируете редукторы в случае использования асинхронных редукторов:export const createRootReducer = asyncReducers => { const appReducer = combineReducers({ myReducer ...asyncReducers }); return (state, action) => { if (action.type === 'LOGOUT_USER') { state = undefined; } return appReducer(state, action); } };
Иво Сабев,
2
if (action.type === 'RESET') return action.stateFromLocalStorage
Дан Абрамов
3
Этот подход полностью очищает государство и всю его историю? Я думаю с точки зрения безопасности: если это было реализовано, после того, как USER_LOGOUTдействие было запущено, возможно ли получить данные о состоянии от ранее? (например, через devtools)
AlexKempton
81

Я хотел бы отметить, что принятый комментарий Дана Абрамова является правильным, за исключением того, что мы столкнулись со странной проблемой при использовании пакетаact-router-redux вместе с этим подходом. Мы решили не устанавливать состояние, undefinedа использовать текущий редуктор маршрутизации. Поэтому я бы предложил реализовать решение ниже, если вы используете этот пакет

const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    const { routing } = state
    state = { routing } 
  }
  return appReducer(state, action)
}
Райан Ирилли
источник
19
Я думаю, что здесь можно сделать вывод, что вы можете не захотеть очищать все дерево состояний при выходе из системы - этот подход одинаково хорошо работает на корневом редукторе любого поддерева, и поэтому может быть более понятным применить эту технику только на корневых редукторах поддерево (s) вы действительно хотите , чтобы очистить, а не выбирать из «особых» детей в не ясно , в корневой редукторе всего дерева, как это
davnicwil
1
Я думаю, что у меня возникли проблемы, на которые вы сейчас ссылаетесь (когда при выходе из системы он устанавливает правильный путь, но загружается совершенно другой компонент), я реализовал что-то похожее на ваше, чтобы это исправить, но я думаю, что-то с Неизменный JS копит это. Я закончил тем, что создал родительский редуктор с действием RESET-STATE, и я наследую от этого редуктора, чтобы вообще не затрагивать маршрутизацию
Neta Meta
Испытывал подобные проблемы, это исправило это. Спасибо.
Ллойд Уоткин
3
Заметьте, что у реакции-redux-router свойство есть routerи НЕrounting
Mrchief
2
@Mrchief это зависит от того, что вы определили, как это в вашем combineReducers()..... если бы у вас было, combineReducers({routing: routingReducer})как было бы описано в ответе
Бен Lonsdale
40

Определите действие:

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действие, вы обновляете хранилище с состоянием по умолчанию.

Теперь для выхода из системы вы можете выполнить следующее:

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. Однако в обоих случаях вы можете отправить другое действие «СБРОС». Таким образом, выход из магазина и сброс будут происходить синхронно, и ваш магазин будет готов для входа другого пользователя.

nirbhaygp
источник
1
Я чувствую, что это лучший подход, чем просто установить состояние, undefinedкак в другом ответе. когда ваше приложение ожидает дерево состояний и вы даете его undefinedвместо этого, есть только больше ошибок и головных болей, чем просто пустое дерево.
worc
3
@worc Состояние на самом деле не будет неопределенным, потому что редукторы возвращают initialState при получении неопределенного состояния
Гийом,
3
@worc считает, что при таком подходе каждый раз, когда кто-либо создает новый редуктор, вы должны помнить о необходимости добавления случая сброса.
Франкфурт
1
Я определенно изменил свое мнение по этим двум причинам, плюс идея о том, что RESET_ACTION - это действие . поэтому он не относится к редуктору с самого начала.
Worc
1
Это определенно правильный подход. Установка состояния на что угодно, кроме начального состояния, просто
Себастьян Серрано
15

Просто упрощенный ответ на лучший ответ:

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


export default (state, action) =>
  rootReducer(action.type === 'USER_LOGOUT' ? undefined : state, action);
Мэтт Карлотта
источник
это работает, спасибо, я был от ответа Дэна, но я не могу понять это.
Алджон Ямаро
14
 const reducer = (state = initialState, { type, payload }) => {

   switch (type) {
      case RESET_STORE: {
        state = initialState
      }
        break
   }

   return state
 }

Вы также можете запустить действие, которое обрабатывается всеми или некоторыми редукторами, которые вы хотите сбросить в исходное хранилище. Одно действие может вызвать сброс к вашему состоянию в целом или просто к его части, которая кажется вам подходящей. Я считаю, что это самый простой и самый контролируемый способ сделать это.

Даниил Петров
источник
10

С Redux if применили следующее решение, которое предполагает, что я установил initialState во всех моих редукторах (например, {user: {name, email}}). Во многих компонентах я проверяю эти вложенные свойства, поэтому с помощью этого исправления я предотвращаю сбои моих методов рендеринга в условиях связанных свойств (например, если state.user.email, который выдаст ошибку, не определен пользователем, если упомянутые выше решения).

const appReducer = combineReducers({
  tabs,
  user
})

const initialState = appReducer({}, {})

const rootReducer = (state, action) => {
  if (action.type === 'LOG_OUT') {
    state = initialState
  }

  return appReducer(state, action)
}
Роб Мурман
источник
7

ОБНОВЛЕНИЕ NGRX4

Если вы переходите на NGRX 4, вы, возможно, заметили из руководства по миграции, что метод rootreducer для объединения ваших редукторов был заменен методом ActionReducerMap. Во-первых, этот новый способ действий может сделать сброс состояния вызовом. Это на самом деле просто, но способ сделать это изменился.

Это решение вдохновлено разделом API метаредукторов документации NGRX4 Github.

Во-первых, предположим, что вы комбинируете свои редукторы, как это, используя новую опцию ActionGReducerMap в NGRX:

//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.

Тайлер Браун
источник
5

Комбинируя подходы Дэна, Райана и Роба для учета routerсостояния и инициализации всего остального в дереве состояний, я получил следующее:

const rootReducer = (state, action) => appReducer(action.type === LOGOUT ? {
    ...appReducer({}, {}),
    router: state && state.router || {}
  } : state, action);
Andy_D
источник
4

Я создал компонент, чтобы дать Redux возможность сброса состояния, вам просто нужно использовать этот компонент для улучшения вашего хранилища и отправки определенного action.type для запуска сброса. Мысль о реализации такая же, как и то, что сказал @Dan Abramov.

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

wwayne
источник
4

Я создал действия, чтобы очистить государство. Поэтому, когда я отправляю создателя действий выхода из системы, я также отправляю действия для очистки состояния.

Действие записи пользователя

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

Я не уверен, что это оптимально?

Навинеш Чанд
источник
2

Если вы используете redux-действия , вот быстрый обходной путь, используя HOF ( функцию более высокого порядка ) для handleActions.

import { handleActions } from 'redux-actions';

export function handleActionsEx(reducer, initialState) {
  const enhancedReducer = {
    ...reducer,
    RESET: () => initialState
  };
  return handleActions(enhancedReducer, initialState);
}

А потом использовать handleActionsExвместо оригинала handleActionsдля обработки редукторов.

Ответ Дэна дает отличное представление об этой проблеме, но она не сработала для меня, потому что я использую redux-persist.
При использовании с redux-persistпростым передачей undefinedсостояния не запускалось постоянное поведение, поэтому я знал, что должен был вручную удалить элемент из хранилища (таким образом, в моем случае это React Native AsyncStorage).

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

или

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

у меня тоже не получилось - они просто наорали на меня. (например, жалоба типа «Неожиданный ключ _persist ...» )

Затем я внезапно подумал, что все, что я хочу, это просто заставить каждый отдельный редуктор возвращать свое собственное начальное состояние при RESETобнаружении типа действия. Таким образом, упорство обрабатывается естественно. Очевидно, что без использования служебной функции ( handleActionsEx) мой код не будет выглядеть СУХИМ (хотя это всего лишь одна строка, т.е. RESET: () => initialState), но я не мог этого вынести, потому что я люблю метапрограммирование.

elquimista
источник
2

Следующее решение сработало для меня.

Я добавил функцию сброса состояния в мета редукторы. Ключ должен был использовать

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 {}
Пан Петр
источник
2

С точкой зрения безопасности, безопаснее всего делать , когда выход из системы , чтобы сбросить все постоянное состояние (бывшее печенье, localStorage, IndexedDB, Web SQLи т.д.) и сделать жесткое обновление страницы с помощью window.location.reload(). Возможно, неаккуратный разработчик случайно или намеренно сохранил некоторые конфиденциальные данные windowв DOM и т. Д. Сброс всех постоянных состояний и обновление браузера - единственный способ гарантировать, что информация от предыдущего пользователя не будет передана следующему пользователю.

(Конечно, как пользователь на компьютере с общим доступом, вы должны использовать режим «частного просмотра», самостоятельно закрывать окно браузера, использовать функцию «очистки данных просмотра» и т. Д., Но как разработчик мы не можем ожидать, что все всегда будут прилежный)

tlrobinson
источник
1
Почему люди отвергли это? Когда вы создаете новое избыточное состояние с пустым содержимым, у вас все еще остаются предыдущие состояния в памяти, и вы можете теоретически получить доступ к данным из них. Обновление браузера - ваша самая безопасная ставка!
Вильгельм Сорбан,
2

Мой обходной путь при работе с машинописью, основанной на ответе Дэна (избыточные типизации делают невозможным переход undefinedк редуктору в качестве первого аргумента, поэтому я кеширую начальное корневое состояние в константу):

// 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"})
  }
}
Jacka
источник
2

Принятый ответ помог мне решить мой случай. Однако я столкнулся со случаем, когда необходимо очистить не все состояние. Итак - я сделал это так:

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 состояний, но я хочу сбросить состояние только одного редуктора?
Павел
1

Просто расширение ответа @ 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);
};
gsaandy
источник
1

Быстрая и простая опция, которая работала для меня, использовала 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'
})

Надеюсь это поможет

Муней Ненгвенани
источник
1

Мое предположение, чтобы 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;
  }
};
Хани
источник
Идея написать состояние по умолчанию как функцию действительно спасла день. Спасибо 🙏
Крис Пол
0

Этот подход очень правильный: уничтожить любое конкретное состояние «ИМЯ», чтобы игнорировать и удерживать других.

const rootReducer = (state, action) => {
    if (action.type === 'USER_LOGOUT') {
        state.NAME = undefined
    }
    return appReducer(state, action)
}
Халил Зайдун
источник
Если вам нужно сбросить только одну часть вашего дерева состояний, вы также можете прослушать USER_LOGOUTэтот редуктор и обработать его там.
Andy_D
0

почему бы тебе просто не использовать 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;
}

Примечание: убедитесь, что вы установили значение по умолчанию для действия, {}и у вас все в порядке, потому что вы не хотите, чтобы action.typeпроизошла ошибка при проверке внутри оператора switch.

Фарид Алнамрути
источник
0

Я обнаружил, что принятый ответ хорошо работает для меня, но он вызвал no-param-reassignошибку ESLint - 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)
}

Но, может быть, создание копии состояния для простой передачи ее в другую функцию-редуктор, которая создает копию, которая немного сложнее? Это выглядит не так хорошо, но более конкретно:

export default (state, action) => {
    return appReducer(action.type === "LOGOUT" ? undefined : state, action)
}
skwidbreth
источник
0

В дополнение к ответу Дана Абрамова, не должны ли мы явно установить действие как action = {type: '@@ INIT'} рядом с state = undefined. При указанном выше типе действия каждый редуктор возвращает исходное состояние.

рупав джайн
источник
0

на сервере у меня есть переменная: global.isSsr = true, и в каждом редукторе у меня есть const: initialState Чтобы сбросить данные в хранилище, я делаю следующее с каждым редуктором: пример с 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
});
Ngannv
источник
0

Следующее решение работает для меня.

Сначала при запуске нашего приложения состояние редуктора является новым и новым по умолчанию InitialState .

Мы должны добавить действие, которое вызывает начальную загрузку приложения для сохранения состояния по умолчанию .

При выходе из приложения мы можем просто переназначить состояние по умолчанию, и редуктор будет работать как новый .

Основной 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
    });
  }
}

Надеюсь, это решит вашу проблему!

Mukundhan
источник
0

Для того чтобы сбросить состояние до его начального состояния, я написал следующий код:

const appReducers = (state, action) =>
   combineReducers({ reducer1, reducer2, user })(
     action.type === "LOGOUT" ? undefined : state,
     action
);
JDev
источник
0

Единственное, что решение в принятом ответе не делает, это очистить кэш для параметризованных селекторов. Если у вас есть такой селектор:

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 .

Grochni
источник
0

для меня лучше всего было бы установить initialStateвместо state:

  const reducer = createReducer(initialState,
  on(proofActions.cleanAdditionalInsuredState, (state, action) => ({
    ...initialState
  })),
Ной Леви
источник
-1

Другим вариантом является:

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

'@@redux/INIT'это тип действия, который при вашей редукции отправляет автоматически createStore, так что, если у ваших редукторов уже есть значение по умолчанию, они будут перехвачены и начнут ваше состояние заново. Впрочем, это можно считать частной реализацией избыточности, так что покупатель остерегается ...

lobati
источник
Я сделал, чтобы это не меняло состояние, также я попытался @@ INIT, который показан в ReduxDevtools как первое действие
Реза
-2

Просто очистите сеанс по ссылке на выход из системы и обновите страницу. Для вашего магазина не требуется дополнительный код. Каждый раз, когда вы хотите полностью сбросить состояние, обновление страницы - это простой и легко повторяемый способ справиться с этим.

user3500325
источник
1
Что если вы используете промежуточное ПО, которое синхронизирует магазин с локальным хранилищем? Тогда ваш подход не работает вообще ...
Спок
8
Я не очень понимаю, почему люди понизили ответы на подобные вопросы.
Уильям Джадд
Почему люди отвергли это? Когда вы создаете новое избыточное состояние с пустым содержимым, у вас все еще остаются предыдущие состояния в памяти, и вы можете теоретически получить доступ к данным из них. Обновление браузера - ваша самая безопасная ставка!
Вильгельм Сорбан
-3

onLogout() {
  this.props.history.push('/login'); // send user to login page
  window.location.reload(); // refresh the page
}

Никита Безносиков
источник
объяснить? @SinanSamet
Никита Безносиков,
Чтобы было ясно, я не проголосовал за это. Но я не одобряю это. Если вы войдете в систему и перезагрузите систему, вы, вероятно, выйдете из системы. Да. Но только потому, что вы потеряли свое состояние. Если вы не используете redux-persist, в этом случае вы даже не выйдете из системы. В целом, я просто ненавижу видеть такие функции, какwindow.location.reload();
Синан Самет
- Не пишите такие функции, как это. - Почему? - Мне это не нравится.
Никита Безносиков
1
Перезагрузка страницы отличается от сброса состояния магазина. Кроме того, вы можете находиться в окружающей среде без window, например,
Макс