Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v5] PersistGate never renders because rehydrate never gets called #603

Open
millermatt opened this issue Dec 5, 2017 · 19 comments
Open

Comments

@millermatt
Copy link

millermatt commented Dec 5, 2017

I'm trying redux-persist for the first time, but can't get my normal render through PersistGate.

function createPersistentStore ( persistenceKey ) {
    const persistConfig = {
        key: persistenceKey,
        storage,
    };

    /***** APP REDUCER *****/
    const appReducer = persistCombineReducers( persistConfig, reducerConfig );

    /***** STORE *****/
    const store = createStore( appReducer, undefined, applyMiddleware( thunk ) );
    const persistor = persistStore( store );

    return {
        persistor,
        store
    };
}

const { store, persistor } = createPersistentStore( 'foo' );

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

export default class App extends React.Component {
    render() {
        return (
            <Provider store={ store } >
                <PersistGate
                    loading={ null }
                    onBeforeLift={ onBeforeLift }
                    persistor={ persistor }>
                    <Loaded />
                </PersistGate>
            </Provider>
        );
    }
}

const Loaded = () => {
    console.log( 'loaded' );
    return ( <View><Text>loaded</Text></View> );
};

The page is blank and loaded is never logged.

When this code runs in persistStore.js, it dispatches to reducers that are props of the reducerConfig that I passed to persistCombineReducers(), but rehydrate() is never called:

  persistor.persist = function () {
    store.dispatch({ type: _constants.PERSIST, register: register, rehydrate: rehydrate });
  };

Is there more I have to do that is not documented in the readme? Do I need to handle the PERSIST action myself and call rehydrate myself?

Thanks,
Matt

@rt2zz
Copy link
Owner

rt2zz commented Dec 5, 2017

REHYDRATE will be called by the persisted reducer after it gets state.

Some things to help debug:

  1. you can add debug: true to persist config for extra logging
  2. put a breakpoint in the persistReducer.js handling of PERSIST action, make sure it is coming and and that getStoredState is being called.

@henrytao-me
Copy link

I have the same problem. Can you look into it @rt2zz ?

@henrytao-me
Copy link

I found the issue. AsyncStorage.getItem was broken on [email protected] facebook/react-native#14101. Upgrading to [email protected] fixed this issue. @millermatt

@rystraum
Copy link

rystraum commented Dec 8, 2017

Just wanted to add here that upgrading to [email protected] isn't an option for those using expo at the moment. Latest expo version available on the app store only supports 0.50.4.

@giacomocerquone
Copy link

giacomocerquone commented Dec 11, 2017

I've updated react native but still got the same problem! It works only if I call persistor.purge() on didmount, anyone knows why?
Onbeforelift is working too and attaching a reducer to "REHYDRATE" works

@henrytao-me
Copy link

Sometime, I do get this issue, rehydrated === false. I have to kill the app and restart. It is quite annoying. It is good to know that persistor.purge will work.

@giacomocerquone
Copy link

giacomocerquone commented Dec 11, 2017

Actually I have even a stranger behaviour. If I don't use persistor.purge() the component inside PersistGate call an action creator but then this component will not update e componentwillreceiveprops is not called, if I put that persistor.purge (or completely remove persistgate) it works... guys I'm going nuts with this, what could it be? @rt2zz

@rt2zz
Copy link
Owner

rt2zz commented Dec 11, 2017

I am not clear what exactly the issue is can you restate the entirety of the problem?

@henrytao-me you are saying you see rehydrated === false even after rehydration completes ocassionally?

@nenti
Copy link

nenti commented Jan 24, 2018

This is a really ugly issue that I had in v4 already and now I upgraded to v5 and it is still the case. Easy way to reproduce:

  1. Put a debugger breakpoint in your main App.js render function.
  2. Reload after PERSIST and before REHYDRATE action
  3. REHYDRATE wille never be called again until you kill the app an restart it

@henrytao-me
Copy link

As I know, this is not a problem from redux-persist. AsyncStorage.getItem does not trigger some time during on reload that cause redux-persist does not rehydrated. The only way to fix it is killing the app.

@nenti
Copy link

nenti commented Jan 24, 2018

Thank you for the info. I will try dropping Redux persist and get my items directly.

  1. Is there a related issue open in react-native?
  2. Is there a way to handle missing response programmatically? Or another storage I can use?
  3. Does this happen in production aswell?

This bug makes usage a pain, especially when you use react - native auto reload function.

@henrytao-me
Copy link

henrytao-me commented Jan 24, 2018

@nenti There is an issue here for your reference. facebook/react-native#14101

I haven't encounter this issue (at least as often as I notice) since I use this

    "react": "16.0.0",
    "react-native": "0.51.0",
    "react-redux": "5.0.6",

@nenti
Copy link

nenti commented Jan 24, 2018

@henrytao-me I have almost the same versioning as you. From my research it is an android issue with debugger connected and for hot- and live-reloading.

  "react-native": "0.52.1",
  "react-redux": "5.0.6",

It is totally annoying because ofc when you develop debugger is connected and you use reload functions. And the worst part is when you work in a team and your team does not know about this issue.

@costagolub
Copy link

In my case updating to the latest versions didn't help me. The app stops working at some moment, rehydrade/persist action never calls, nothing helps except killing the emulator and re-start the react-native. Is it possible to call rehydrate action without PersistGate? Or any other solutions would be good. Thanks!

@rt2zz
Copy link
Owner

rt2zz commented Feb 2, 2018

So given the issue is in the underlying storage layer, I think the only remedy redux-persist can offer is a timeout config that will set a max time for rehydration before giving up.

Also I would recommend considering an alternative storage adapter, e.g. https://github.com/robwalkerco/redux-persist-filesystem-storage

@rt2zz
Copy link
Owner

rt2zz commented Feb 3, 2018

FYI we are currently contemplating adding timeout in this PR #702

That would at least give users some recourse (without the need to switch storage adapters)

@ali-sao
Copy link

ali-sao commented Jul 11, 2018

Try to define your persistor inside component constructor :

import store from './store';

class App extends Component {
  constructor() {
    super();
    this.persistor = persistStore(store);
  }
  render() {

    return (
      <Provider store={store}>
        <PersistGate persistor={this.persistor} loading={null}>
          <RootRouter />
        </PersistGate>
      </Provider>
    )
  }
}

@joshimbriani
Copy link

Switching the default redux-persist store to redux-persist-filesystem-storage fixed this issue for me!

@Clementol
Copy link

Try to define your persistor inside component constructor :

import store from './store';

class App extends Component {
  constructor() {
    super();
    this.persistor = persistStore(store);
  }
  render() {

    return (
      <Provider store={store}>
        <PersistGate persistor={this.persistor} loading={null}>
          <RootRouter />
        </PersistGate>
      </Provider>
    )
  }
}

@ali-sao you saved with your codes. thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants