rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.97k stars 867 forks source link

v5 - TypeError: In this environment the sources for assign MUST be an object.This error is a performance optimization and not spec compliant #536

Open ranggarifqi opened 7 years ago

ranggarifqi commented 7 years ago

Hey, umm... i've tried to implement redux persist for my project... After i followed your documentation on how to implement this module, there's no problem.

but, when i tried to reload the app...Then it shows a blank white screen and shows warning TypeError: In this environment the sources for assign MUST be an object.This error is a performance optimization and not spec compliant

Then, i tried to change the config key from root to anything... like rootzzz. And it actually works. But then when i tried to change it again to root, it shows this blank screen again, with those warning

I don't understand what's going on... could you help me ?

this is my reducer list ./src/reducers/index.js

import {combineReducers} from 'redux';
import { persistCombineReducers } from 'redux-persist'
import storage from 'redux-persist/es/storage';

const config = {
  key: 'root',
  storage,
}

import { reducer as formReducer } from 'redux-form'
import AuthReducer from './AuthReducer';
import SideMenuReducer from './SideMenuReducer';
import SideMenuSelectReducer from './SideMenuSelectReducer';
import HomeDashReducer from './HomeDashReducer';

const reducers = {
    form: formReducer,
    auth : AuthReducer,
    sidemenus: SideMenuReducer,
    selectedMenuId : SideMenuSelectReducer,
    menuHome : HomeDashReducer
}
export default persistCombineReducers(config, reducers);

and this is my code for ./App.js

import React, {Component} from 'react';
import {View} from 'react-native';
import expo from 'expo';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import ReduxThunk from 'redux-thunk';
import reducers from './src/reducers';
import Router from './src/Router';

import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/es/integration/react';

function configureStore () {
  // ...
  let store = createStore(reducers, {}, applyMiddleware(ReduxThunk))
  let persistor = persistStore(store)

  return { persistor, store }
}

class App extends Component{

    async componentWillMount(){
        expo.Font.loadAsync({
          'Roboto_medium': require('./assets/fonts/Roboto_medium.ttf'),
        });
    }

    onBeforeLift = () => {
      // take some action before the gate lifts
    }

    render(){
        const { persistor, store } = configureStore();
        return(

            <Provider store={store}>
                <PersistGate
                    loading={<View />}
                    onBeforeLift={this.onBeforeLift}
                    persistor={persistor}
                >
                    <Router/>
              </PersistGate>

            </Provider>
        );
    }
}

export default App;

Is there anything wrong with my code ? its been 3 hours and i still have no clue

Thanks :)

cheneywan commented 7 years ago

The same problem..

Cariosvertel commented 7 years ago

Same problem too. FYI, you can customize blank screen by modifying this line loading={<View />}. I know it's something trivial because it's detailed on doc, but I known it could be helpful for someone who read this post.

AlessandroAnnini commented 7 years ago

Same issue here.. the only difference is that I use AsyncStorage (that should be the proper choice with RN) and i see the component assigned to loading but then I'm stuck too

import { AsyncStorage } from 'react-native';

const config = {
  key: 'root',
  storage: AsyncStorage
};
Cariosvertel commented 7 years ago

according to this line where error is fired, it should accept an object as payload, and seems that just stored data isn't being provided as it.

AlessandroAnnini commented 7 years ago

@ranggarifqi , @Cariosvertel .. it all started working after a complete uninstall of the app and a new deploy with react-native run-android. Maybe the store was sill there but in a v4 fashion and everything, that's why you need to migrate or completely reinstall the app

Cariosvertel commented 7 years ago

@sun2rise I tried this line:

watchman watch-del-all && rm -rf $TMPDIR/react-* && rm -rf node_modules/ && npm cache clean && npm install && npm start -- --reset-cache

in order to reset my project but no success.

jmcol commented 7 years ago

I'm having the same problem, as well. I reinstalled my client simulator and wiped all my cache. That helped the simulator start working again; however, once I attempted to persist data, I got the error again.

rkleine commented 7 years ago

I was having the same issue. This maybe is because you have a state with a root key that the value is not an object, for example:

{
  posts: [], // this is ok, is an object
  agreeToC: false // this is causing the issue because false can be deserialized
}

When trying to deserialized the above object will throw the error. Try to change to something like this

{
  posts: [], // this is ok, is an object.
  agreeToC: { accept: false } // this will fix the issue
}

If you already have a persiste store with the error:

  1. Add this line persistor.purge(); after const persistor = persistStore(store);
  2. Reload the app so the store is purged,
  3. Remove/comment the line persistor.purge();
  4. Reload the app and see if the issue is fixed

@rt2zz can you validate this comment, thanks!

ranggarifqi commented 7 years ago

i ended up using v4 though because of my deadline

Before i decided to use v4, i think this error came from PersistGate

i tried to remove PersistGate and i didnt see the error. But, idk somehow it didnt rehydrate

Well, i'll try to tweak this again if i have time.

rkleine commented 7 years ago

@ranggarifqi do you try my suggestion?

rt2zz commented 7 years ago

that is correct, right now reducer state needs to be objects. I plan to update this in the near future to support non-objects.

rt2zz commented 7 years ago

actually just cut redux-persist@5.3.0-rc which hopefully resolves this. npm i redux-persist@next to test

sachin-sable commented 6 years ago

@rt2zz I have combination of objects and non-objects. I am planning to update to v5 but this is the only thing that is stopping me as I am getting the same error stated above. I am using v5.4.0. Is there something I am missing to add or is my approach correct? Please help.

rt2zz commented 6 years ago

if you have non-object state then you will want to use persistReducer rather than persistCombineReducers.

let rootReducer = combineReducers(reducers)
let persistedReducer = persistReducer(config, rootReducer)
sachin-sable commented 6 years ago

@rt2zz Thank you so much for help. I ended up converting all non object state to objects by grouping related items together. For e.g. globalLoading, error, isConnected, etc are grouped under object called "networkState". Thanks.

rt2zz commented 6 years ago

ya to elaborate a little bit, persistReducer only shallow merges 1 level or state, while persistCombineReducers merges 2.

Still looking for how to surface these options in a developer friendly way... but ya for now persistReducer should be the way to go for your case 👍

rochapablo commented 6 years ago

I tried to change to

// const reducer = persistCombineReducers(config, reducers)
let rootReducer = combineReducers(reducers)
let reducer = persistReducer(config, rootReducer)

but it keeps getting

ExceptionsManager.js:73 Notification handler err TypeError: In this environment the sources for assign MUST be an object.This error is a performance optimization and not spec compliant.
    at Object.assign (Object.es6.js:42)
"react-redux": "^5.0.6"
"redux-persist": "^5.4.0"

UPDATE

I believe have fix the problem; I was getting something like { store: { 'user: { name: 'Fox' }' } } a cup of coffee and JSON.parse solved my case.

DalalAbadi commented 6 years ago

I am using firebase and react-redux and I solved this issue by adding this line

import _ from 'lodash';

chrisbull commented 6 years ago

I get this error with redux-persist@5.7.2 when I import autoMergeLevel2: import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2'

rt2zz commented 6 years ago

@chrisbull are you using immutablejs?