Gdzie pisać do localStorage w aplikacji Redux?

Chcę przenieść niektóre części mojego drzewa stanu do localStorage. Jakie jest do tego odpowiednie miejsce? Reduktor czy działanie?

Author: Damjan Pavlica, 2016-02-10

5 answers

Reduktor nigdy nie jest odpowiednim miejscem, aby to zrobić, ponieważ reduktory powinny być czyste i nie mają skutków ubocznych.

Polecam po prostu zrobić to w abonencie:

store.subscribe(() => {
  // persist your state
})

Przed utworzeniem sklepu przeczytaj te części:

const persistedState = // ...
const store = createStore(reducer, persistedState)

Jeśli użyjesz combineReducers() zauważysz, że reduktory, które nie otrzymały stanu, będą "uruchamiać się" normalnie, używając domyślnej wartości argumentu state. To może być bardzo przydatne.

Wskazane jest, aby zdemaskować swojego Abonenta tak nie piszesz do localStorage zbyt szybko, bo będziesz miał problemy z wydajnością.

W końcu możesz stworzyć oprogramowanie pośredniczące, które enkapsuje to jako alternatywę, ale zacznę od abonenta, ponieważ jest to prostsze rozwiązanie i dobrze wykonuje swoją pracę.
 147
Author: Dan Abramov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-27 20:52:00

Aby wypełnić puste pola odpowiedzi dana Abramova, możesz użyć store.subscribe() w następujący sposób:

store.subscribe(()=>{
  localStorage.setItem('reduxState', JSON.stringify(store.getState()))
})

Przed utworzeniem sklepu, sprawdź localStorage i przeanalizuj dowolny JSON pod Twoim kluczem w następujący sposób:

const persistedState = localStorage.getItem('reduxState') ? JSON.parse(localStorage.getItem('reduxState')) : {}

Następnie przekazujesz tę peristedState stałą do swojej metody createStore w następujący sposób:

const store = createStore(
  reducer, 
  persistedState,
  /* any middleware... */
)
 114
Author: Andrew Samuelsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-07 23:12:13

Jednym słowem: middleware.

Sprawdź redux-persist . Albo napisz własną.

[UPDATE 18 Dec 2016] Edited to remove mention of two similar projects now inactive or deprecated.

 38
Author: David L. Walsh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-17 21:48:28

Jeśli ktoś ma jakiś problem z powyższymi rozwiązaniami, może napisać własne. Pokażę Ci, co zrobiłem. Ignoruj saga middleware rzeczy po prostu skup się na dwóch rzeczach localStorageMiddleware i reHydrateStore metoda. w tym celu należy pobrać wszystkie pliki z katalogu i umieścić je w local storage i rehydrateStore w lokalnym magazynie, jeśli są dostępne i umieścić je w redux store

import {createStore, applyMiddleware} from 'redux'
import createSagaMiddleware from 'redux-saga';
import decoristReducers from '../reducers/decorist_reducer'

import sagas from '../sagas/sagas';

const sagaMiddleware = createSagaMiddleware();

/**
 * Add all the state in local storage
 * @param getState
 * @returns {function(*): function(*=)}
 */
const localStorageMiddleware = ({getState}) => { // <--- FOCUS HERE
    return (next) => (action) => {
        const result = next(action);
        localStorage.setItem('applicationState', JSON.stringify(
            getState()
        ));
        return result;
    };
};


const reHydrateStore = () => { // <-- FOCUS HERE

    if (localStorage.getItem('applicationState') !== null) {
        return JSON.parse(localStorage.getItem('applicationState')) // re-hydrate the store

    }
}


const store = createStore(
    decoristReducers,
    reHydrateStore(),// <-- FOCUS HERE
    applyMiddleware(
        sagaMiddleware,
        localStorageMiddleware,// <-- FOCUS HERE 
    )
)

sagaMiddleware.run(sagas);

export default store;
 5
Author: Gardezi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-03 13:19:25

Nie mogę odpowiedzieć @Gardezi, ale opcja oparta na jego kodzie może być:

const rootReducer = combineReducers({
    users: authReducer,
});

const localStorageMiddleware = ({ getState }) => {
    return next => action => {
        const result = next(action);
        if ([ ACTIONS.LOGIN ].includes(result.type)) {
            localStorage.setItem(appConstants.APP_STATE, JSON.stringify(getState()))
        }
        return result;
    };
};

const reHydrateStore = () => {
    const data = localStorage.getItem(appConstants.APP_STATE);
    if (data) {
        return JSON.parse(data);
    }
    return undefined;
};

return createStore(
    rootReducer,
    reHydrateStore(),
    applyMiddleware(
        thunk,
        localStorageMiddleware
    )
);

Różnica polega na tym, że zapisujemy tylko niektóre akcje, możesz użyć funkcji debounce, aby zapisać tylko ostatnią interakcję twojego stanu

 1
Author: Douglas Caina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-01 14:59:04