rt2zz / redux-persist

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

Bug: Android webview does not persist data fast enough #1252

Open dannyskim opened 4 years ago

dannyskim commented 4 years ago

What is the current behavior?

Currently have a React project where I am bridging calls back and forth between iOS and Android. I have made a mobile native wrapper around a Webview on both iOS/Android, and native methods are in place to direct the user to a specific React webpage to mimic native screens instead of building them natively.

We have a blank React landing page to handle the redirects and intercepting of the data via the javascript postMessage bridge. A boolean flag is set to denote that the React app is being browsed via mobile native Webview in redux state, and then in a useEffect waiting for this flag to be set, the user is redirected to the intended page/route. Redirecting is a mix between utilizing react router and directly via window.location.

In the useEffect, the boolean flag is updated and then redirect is issued, but when utilizing window.location, the next page grabs the boolean flag via selector and it has been reset.

This appears to only happen in the Android Webview. Have not provided a code sample as this issue can only be replicated in the Android Webview as far as I can tell.

What is the expected behavior?

When boolean flag is set to true in useEffect and user is redirected via window.location, would expect that the boolean flag stays true instead of being reset to false.

My understanding is that the Android Webview is an entirely separate Chromium view and most likely uses a different Local Storage methodology in Android. I suspect a sort of race condition is happening where redux thinks it's state has been committed to local storage, but then when utilizing window.location and navigating away too fast, the next page rehydrates the store and commits have not yet finished.

My suspicion is confirmed by utilizing a setTimeout to delay the window.location redirect of 100ms, in which redux then reliably produces the expected values from the persist store.

dhamursv commented 2 years ago

Wrap your root component with PersistGate. This delays the rendering of your app's UI until your persisted state has been retrieved and saved to redux.

import { PersistGate } from 'redux-persist/integration/react'
import { SpinnerLoader } from "./common.style";

const App = () => {
  return (
    <Provider store={store}>
      <PersistGate loading={<SpinnerLoader />} persistor={persistor}>
        <RootComponent />
      </PersistGate>
    </Provider>
  );
};