redux-persist v5:状态不存在于ASyncStorage中

时间:2018-04-06 14:25:00

标签: android react-native redux redux-persist

我已经尝试了一个星期或更长时间使我的状态持续存在于一个反应原生的Android应用程序中,但在重新水化之后,状态始终具有初始值。如果我检查ASyncStorage内容或具有Redux devtools的状态,则它是初始状态:

{
   "status":"{\"actions\":[]}",
   "list":"{\"actions\":[]}",
   "map":"{\"site_ids\":{},\"alarmCounts\":[],\"geoJSON\":{}}",
   "_persist":"{\"version\":-1,\"rehydrated\":true}"
}

当我使用redux-reset并且无法从Google找到任何解决方案时,我也会收到错误Unexpected key "_persist" ...

如果我运行store.flush()store.purge(),我在ASyncStorage中看不到任何更改。

我的configureStore文件如下。我认为这个问题就在这里。有什么帮助吗?

import { createStore } from "redux";
import { composeWithDevTools } from 'redux-devtools-extension';
import { persistStore, persistCombineReducers } from "redux-persist";
import reduxReset from 'redux-reset';
import { AsyncStorage } from 'react-native'

import userReducer from '../reducers/user';
import statusReducer from '../reducers/status';
import listReducer from '../reducers/list';
import mapReducer from '../reducers/map';

function reset(): void {
    console.log('Reseting state');
    store.dispatch({
      type: 'RESET'
    });
    // persistor.purge();
};

function flush() {
    console.log('FLUSH');
    persistor.flush();
}

const enhancer = composeWithDevTools(
    reduxReset()
);

const appReducer = persistCombineReducers(
    { // cfg
        key: 'primary',
        storage: AsyncStorage,
        blacklist: ['user'],
        throttle: 1000
    },
    {
        user: userReducer,
        status: statusReducer,
        list: listReducer,
        map: mapReducer
    }
);

const rootReducer = (state, action) => {
  return appReducer(state, action);
}

const store = createStore(
    rootReducer,
    enhancer
);

const persistor = persistStore(store, null);

export default { store, persistor, reset, flush };

我使用redux@3.7.2,redux-persist @5.9.1,react-native@0.54.0

5 个答案:

答案 0 :(得分:1)

这不是问题的直接答案,而是为这个问题提供了替代解决方案和一些观点。

我不熟悉redux-persist或它的功能,但我本人更喜欢在redux中制作自己的中间件。

import initState from "./reducers/InitiateReducer"

let initialState = initState

将数据保存到LocalStorage的中间件

const localStoreMiddleware = (store) => (next) => (action) => {
  // Get previously stored state
  const ls = localStorage.getItem("reduxState") || null

  let state = {
    application: {}
  }

  if (ls) {
    state = { ...JSON.parse(ls) }
  }
  // Actions that will be required to save data to localStore
  switch (action.type) {
    case "APP_SESSION":
      state.application.session = { ...action.payload.session }
      break
    case "VERIFICATION_DONE":
      state.application.verification_required = false
      break
  }

  localStorage.setItem("reduxState", JSON.stringify(state))
  next(action)
}

将LocalStorage传递给initialState变量并传递值

if (localStorage.getItem("reduxState") !== null) {
  const ls = JSON.parse(localStorage.getItem("reduxState")) || {}

  if (ls.application) {
    if (ls.application.session) {
      initialState.application.session = ls.application.session
    }
    initialState.application.verification_required =
      ls.application.verification_required
  }
}

使用initialState创建商店变量

const store = () => {
  return createStore(
    rootReducer,
    initialState,
    applyMiddleware(
      thunkMiddleware,
      localStoreMiddleware
    )
  )
}

export default store

此功能是使用浏览器的localStorage进行的,但可以在React Native中使用相同的意识形态并使用asyncStorage。然后,您只需将您喜欢的组件包装到connect()并在您想要的变量上使用mapStateToProps。

我很抱歉没有给React Native做好准备解决方案,我会在周末更深入地讨论这个问题。

答案 1 :(得分:0)

尝试以这种方式坚持AsyncStorage

persistStore(store, {storage: AsyncStorage})

答案 2 :(得分:0)

我改变了:

const store = createStore(
    persistReducer,
    enhancers
);

为:

const store = createStore(
    persistReducer,
    undefined,
    enhancers
);

现在,如果我执行store.flush(),它会持续存在,但不会在每次状态更改时自动执行。它虽然(前景/后台)在应用程序状态更改时刷新了。

答案 3 :(得分:0)

这是一个简单的例子,您可以在每次点击按钮后观察状态更改后更改AsyncStorage值:

import PropTypes from 'prop-types'
import React, { Component } from 'react';
import { applyMiddleware, compose, createStore } from 'redux'
import { AsyncStorage, AppRegistry, Button, StyleSheet, Text, View } from 'react-native';
import { combineReducers, Provider, connect } from 'react-redux'
import { persistStore, persistCombineReducers, autoRehydrate} from 'redux-persist'
import thunk from 'redux-thunk';

class Counter extends Component {
    render() {
        const { value, onIncreaseClick,  checkValueInStorage} = this.props
        return (
            <Text>
                <Text>Val: {value}</Text>
                <Button title="Increase" onPress={() => {
                    onIncreaseClick()
                    checkValueInStorage()
                }}/>
            </Text>
        )
    }
}

Counter.propTypes = {
    value: PropTypes.number.isRequired,
    onIncreaseClick: PropTypes.func.isRequired
}

const increaseAction = { type: 'increase' }

function counter(state = { count: 0 }, action) {
    const count = state.count
    switch (action.type) {
        case 'increase':
            return { count: count + 1 }
        default:
            return state
    }
}

const allReducers = {
    counter: counter
};

const persistConfig = {
    key: 'primary',
    storage: AsyncStorage
}

const persistedReducer = persistCombineReducers(persistConfig, allReducers)

const rootReducer = (state, action) => {
    return persistedReducer(state, action);
}
let store = createStore(rootReducer, undefined, applyMiddleware(thunk))
let pers = persistStore(store, null)


function mapStateToProps(state) {
    return {
        value: state.counter.count
    }
}

function mapDispatchToProps(dispatch) {
    return {
        onIncreaseClick: () => dispatch(increaseAction),
        checkValueInStorage: () => {
            AsyncStorage.getItem("persist:root").then(function (specifiVal) {
                console.log("persist:root: Value before delay" + JSON.stringify(specifiVal))
            })

            setTimeout(function () {
                AsyncStorage.getItem("persist:root").then(function (specifiVal) {
                    console.log("Value after delay" + JSON.stringify(specifiVal))
                })
            }, 5000);

        }
    }
}

const AppCounter = connect(
    mapStateToProps,
    mapDispatchToProps
)(Counter)

export default class App extends React.Component {
    render() {
        return (
            <Provider store={store}>
                <View style={styles.container}>
                    <Text>Counter view</Text>
                    <AppCounter/>
                </View>
            </Provider>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center'
    }
});

答案 4 :(得分:0)

轻松修复

用值SELECT Name FROM (SELECT M.ID, D.Name, COUNT(*) as NumActors FROM Director d JOIN Movie m ON d.ID = m.DirectorID JOIN MovieActor ma ON m.ID = ma.MovieID WHERE m.ReleaseDate < '2006-01-01' AND m.Rating >= 9 AND m.DurationMinutes >= 60 GROUP BY D.Name, M.ID HAVING COUNT(*) BETWEEN 3 AND 7 ) m GROUP BY Name HAVING COUNT(*) >= 2;

指定 stateReconciler
hardSet