Як відновити стан магазину Redux?


455

Я використовую Redux для управління державою.
Як повернути магазин до початкового стану?

Наприклад, скажімо, у мене є два облікові записи користувачів ( u1і u2).
Уявіть таку послідовність подій:

  1. Користувач u1заходить у додаток і щось робить, тому ми зберігаємо деякі дані в магазині.

  2. Користувач u1виходить із системи.

  3. Користувач u2увійде в додаток без оновлення браузера.

У цей момент кешовані дані будуть пов’язані u1, і я хотів би їх очистити.

Як я можу відновити магазин Redux до його початкового стану, коли перший користувач вийде з системи?


8
Напевно, краще очистити стан при виході (з точки зору безпеки)
Clarkie

Відповіді:


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-персист зберігає копію вашого стану в двигуні зберігання, і державна копія буде завантажена звідти на оновлення.

Спочатку вам потрібно імпортувати відповідний механізм зберігання даних, а потім проаналізувати стан перед його встановленням 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, який би працював, але не на державі для кожного редуктора.
Cori Danielson

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

Я хотів би зазначити, що прийнятий коментар Дана Абрамова правильний, за винятком випадків, коли ми користувалися пакетом reakct-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
Зауважте, що з реактором-маршрутизатором, властивість є routerі НЕrounting
Mrchief

2
@Mrchief, це залежить від того, що ти це визначив як у своєму combineReducers()..... якщо б у тебе combineReducers({routing: routingReducer})це було, як було описано у відповіді
Бен Лонсдейл

39

Визначте дію:

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. Однак в обох випадках ви можете відправити ще одну дію "RESET". Таким чином вихід із системи зберігання та скидання будуть зберігатися синхронно, і ваш магазин буде готовий до входу іншого користувача.


1
я відчуваю, що це кращий підхід, ніж просто встановлення стану, undefinedяк подобається в іншій відповіді. коли у вашій програмі очікується дерево штату, і ви її undefinedнатомість надаєте , з помилками і головними болями вдається вирішити більше, ніж просто порожнє дерево.
worc

3
@worc Держава насправді не буде визначеною, тому що редуктори повертають початкову державу, коли отримують невизначений стан
Гійом

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

це працює дякую, я був з відповіді Дена, але я не можу це зрозуміти.
Aljohn Yamaro

14
 const reducer = (state = initialState, { type, payload }) => {

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

   return state
 }

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


10

Якщо Redux застосував таке рішення, яке передбачає, що я встановив початкову стан у всіх моїх редукторах (наприклад, {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.

По-перше, скажімо, що ви поєднуєте такі ваші редуктори за допомогою нового параметра ActionReducerMap від 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);

4

Я створив компонент, щоб надати Redux можливість скидання стану, просто потрібно використовувати цей компонент, щоб покращити ваш магазин і відправити певний action.type для запуску скидання. Думка про реалізацію така ж, як сказала @Dan Abramov.

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


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

Якщо ви використовуєте надмірні дії , ось короткий спосіб використання 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), але я не витримав цього, тому що я люблю метапрограмування.


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 тощо. Видування всіх стійких станів та оновлення браузера - це єдиний спосіб гарантувати, що жодна інформація попереднього користувача не просочиться до наступного користувача.

(Звичайно, як користувач на спільному комп'ютері ви повинні використовувати режим "приватного перегляду", самостійно закривати вікно браузера, використовувати функцію "очистити дані перегляду" тощо), але як розробник ми не можемо сподіватися, що всі завжди будуть що старанно)


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

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

1

Швидкий і простий варіант, який працював для мене, використовував функцію redux-reset . Це було просто і має додаткові можливості для великих додатків.

Налаштування в магазині create

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

Цей підхід дуже правильний: знищити будь-який конкретний стан "NAME", щоб ігнорувати та утримувати інших.

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в операторі комутатора.


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

0

Окрім відповіді Дана Абрамова, чи не слід чітко встановлювати дії як action = {type: '@@ INIT'} поряд із state = undefined. З вищевказаним типом дії кожен редуктор повертає початковий стан.


0

на сервері, у мене є змінна: global.isSsr = true і в кожному редукторі, у мене const є: InitiState Щоб скинути дані в магазині, я роблю наступне з кожним редуктором: приклад з 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
});

0

Наступне рішення працює для мене.

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

Ми мусимо додати дію, яка вимагає, щоб вхідне завантаження APP зберігало стан за замовчуванням .

Під час виходу з програми ми можемо просто переназначити стан за замовчуванням, а редуктор працюватиме так само, як і новий .

Основний контейнер додатка

  componentDidMount() {   
    this.props.persistReducerState();
  }

Основний редуктор додатків

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

Сподіваюся, це вирішує вашу проблему!


0

Щоб відновити стан до початкового стану, я написав наступний код:

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

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 .


0

для мене найкраще це встановити initialStateзамість state:

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

-1

Ще один варіант:

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

'@@redux/INIT'- це тип дії, який редукс автоматично надсилає, коли ви createStore, тому припускаючи, що у всіх ваших редукторів вже є за замовчуванням, це може зачепити їх і запустити стан у свіжому стані. Однак це може вважатися приватною деталізацією впровадження скорочення, тому остерігайтеся покупця ...


Я зробив це, що це не змінюється стан, також я спробував @@ INIT, який показаний у ReduxDevtools як перша дія
Reza

-3

Просто проведіть сеанс очищення сеансу та оновіть сторінку. Не потрібен додатковий код для вашого магазину. Будь-який час, коли ви хочете повністю скинути стан оновлення сторінки, це простий і легко повторюваний спосіб обробки.


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, наприклад, рідного реагування
Макс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.