Redux-Persist - как условно сохранить хранилище в react native

Я хочу установить условие для полного сохранения / регидратации магазина или отсутствия в зависимости от того, восстанавливается ли приложение после ошибки.

В компоненте верхнего уровня (app.js) я импортирую хранилище и персистор (из MyStore.js), а остальную часть приложения помещаю в Provider и PersistGate. Хранилище находится в отдельном файле, поэтому его можно импортировать и читать с помощью некоторых общих файлов логики.

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

Буду любить любые предложения

// ......... App.js:

componentDidMount = () => { this.checkForPreviousFatalError() }

checkForPreviousFatalError = async () => {
    var array = null
    try {
        array = await AsyncStorage.multiGet(['@lastFatalErrorEpoch', '@previousFatalErrorEpoch'])
    } catch(e) {
        console.log( "Unable to retrieve date of last 2 errors: " + e );
    }
    const lastError = array[0][1];
    const prevError = array[1][1];

    if ( lastError && prevError && parseInt(prevError) + 60000 > parseInt(lastError) ) {
        // do not persist store
    } else {
        // persist store
    };

}

render() {
    const waitingElement = (
        <ImageBackground source={require('./assets/signInBackground.jpg')} style={[ Styles.flexCenter, Styles.flexColumn, { height: "100%" }]}>
            <Text style={{ fontSize: 18, marginBottom: 20 }} >{ EnglishNA.RestoringLocalData }</Text>
            <Spinner size='large' flexZero={ true } color="white" />
        </ImageBackground>
    )

    return (
        <Provider store={ store }>
            <PersistGate loading={ waitingElement } persistor={ persistor }>
                <LogIn />
            </PersistGate>
        </Provider>
    )

}
}

// ....... MyStore.js

import ReduxThunk from 'redux-thunk';
import { createStore, applyMiddleware } from 'redux';
import ServerCall from './services/ServerCall';
import rootReducer from './reducers'; 
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';

const persistConfig = {
key: 'root',
storage: storage,
stateReconciler: autoMergeLevel2 // see "Merge Process" section for details.
};

const pReducer = persistReducer(persistConfig, rootReducer);

export const store = createStore( pReducer, applyMiddleware( ReduxThunk, ServerCall ) );
export const persistor = persistStore(store);

person joffet    schedule 31.08.2019    source источник


Ответы (1)


Вы должны настроить хранилище после вызова функции checkForPreviousFatalError. Если есть ошибка, не сохраняйте сохранение и не используйте persistReducer в магазине. Для загрузки вы можете использовать состояние компонента.

Нравится:

const pReducer = persist
    ? persistReducer(persistConfig, rootReducer)
    : rootReducer;

App.js

// ......... App.js:
import configureStore from "./MyStore.js";

//....................

state = {
    isLoading: true,
    store: null
  };

componentDidMount = () => { this.checkForPreviousFatalError() }

checkForPreviousFatalError = async () => {
    var array = null
    try {
        array = await AsyncStorage.multiGet(['@lastFatalErrorEpoch', '@previousFatalErrorEpoch'])
    } catch(e) {
        console.log( "Unable to retrieve date of last 2 errors: " + e );
    }
    const lastError = array[0][1];
    const prevError = array[1][1];

    if ( lastError && prevError && parseInt(prevError) + 60000 > parseInt(lastError) ) {
         this.configureStore(false)
        // do not persist store
    } else {
       this.configureStore(true)
        // persist store
    };

}

configureStore = (persist) => {
    configureStore(persist, store => {
      this.setState({ isLoading: false, store });
    });
  }

render() {
    if (this.state.isLoading) {
      return <ImageBackground source={require('./assets/signInBackground.jpg')} style={[ Styles.flexCenter, Styles.flexColumn, { height: "100%" }]}>
            <Text style={{ fontSize: 18, marginBottom: 20 }} >{ EnglishNA.RestoringLocalData }</Text>
            <Spinner size='large' flexZero={ true } color="white" />
        </ImageBackground>;
    }

    return (
      <View style={{ flex: 1 }}>
        <Provider store={this.state.store}>
          <AppNavigator />
        </Provider>
        {this._renderStatusBarIos()}
        <MessageBar />
      </View>
    );
  }


Файл MyStore.js

import ReduxThunk from "redux-thunk";
import { createStore, applyMiddleware } from "redux";
import ServerCall from "./services/ServerCall";
import rootReducer from "./reducers";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2";

let store;

export default function configureStore(persist, onComplete: Function) {
  const persistConfig = {
    key: "root",
    storage: storage,
    stateReconciler: autoMergeLevel2 // see "Merge Process" section for details.
  };

  const pReducer = persist
    ? persistReducer(persistConfig, rootReducer)
    : rootReducer;

  store = createStore(pReducer, applyMiddleware(ReduxThunk, ServerCall));
  persistStore(store, null, () => onComplete(store));
}


если вы хотите экспортировать магазин, сделайте функцию в MyStore.js

export function getStore() {
  return store;
}
person Mehran Khan    schedule 31.08.2019
comment
Спасибо, Мехран, один вопрос. Причина, по которой я разделил логику хранилища в отдельный файл, заключается в том, чтобы я мог импортировать хранилище в другие (не редукционные) компоненты. В предлагаемом вами коде похоже, что элемент магазина больше не экспортируется. Я правильно понимаю? - person joffet; 31.08.2019
comment
@joffet Ответ обновлен. Пожалуйста, проголосуйте за и отметьте правильный ответ, если это полезно - person Mehran Khan; 31.08.2019
comment
Спасибо, Мехран, мне просто пришлось добавить условие для функции configureStore в MyStore, когда она не сохраняется: if (doPersistStore) {persistStore (store, null, () = ›onComplete (store)); } еще {onComplete (магазин)} - person joffet; 01.09.2019