1

I want to force a page reload (even when navigating using the back button) because in Safari browsers, Safari will load a cached version of the page which is not what we want.

Using React Hooks, I can do this in useEffect.

function MyComponent() {
    useEffect(() => {
        if (typeof window != 'undefined') {
            window.onpageshow = event => {
                if (event.persisted) {
                    window.location.reload()
                }
            }
        }
    }, [])

    return (<div>My Page Content</div>)
}

My question is: when doing this, will the reload repeatedly get called because a reload will trigger a re-render and re-mounting of the component, which in turn will call useEffect, which will then call reload and then get into this infinite cycle?

Another way to do this is to mimic a React class constructor:

function MyComponent() {
    const [reloadHasRun, setReloadHasRun] = useState(false)

    const forceReload = () => {
        if (typeof window !== 'undefined') {
            window.onpageshow = event => {
                if (event.persisted) {
                    window.location.reload()
                }
            }
        }

        setReloadHasRun(true)
    }

    if (!reloadHasRun)
        forceReload()

    return (<div>My Page Content</div>)
}

But again, I have this same question. Does the forcing of the reload get me into this situation where the component is continually being re-rendered, re-mounted, and the reload being called over and over again?

Ultimately, what I want to have happen is when the back button is clicked on Safari, that the previous page is reloaded and not just pulled from cache.

noblerare
  • 10,277
  • 23
  • 78
  • 140
  • Does this answer your question? [How can I force a component to re-render with hooks in React?](https://stackoverflow.com/questions/53215285/how-can-i-force-a-component-to-re-render-with-hooks-in-react) – Shivam Jha Mar 29 '21 at 15:34

1 Answers1

2

Yes, in both cases I expect the page to go in an infinite loop of reloading the page if the component is rendered just when starting up.

React hooks don't have any kind of persistence: They are stateful to the instance of the component that you create, and it gets completely removed when the component unmounts (or when the page unloads)

As an advice, I don't think you need to do this inside a React component... it's just a script you want to run every now-and-then.

The implementation of this script can be anything you want, but I thought of two examples:

if(!window.localStorage.getItem('is-refresh')) {
  window.onpageshow = event => {
    if (event.persisted) {
      window.localStorage.setItem('is-refresh', true);
      window.location.reload();
    }
  }
} else {
  window.localStorage.removeItem('is-refresh');
}

This would always refresh the page exactly once. Or you could go with a timestamp:

const lastUpdate = window.localStorage.getItem('lastUpdate')
const lastUpdateTs = lastUpdate ? Number(lastUpdate) : 0;

if(Date.now() > lastUpdateTs + 3600) {
  window.onpageshow = event => {
    if (event.persisted) {
      window.localStorage.set('lastUpdate', Date.now());
      window.location.reload();
    }
  }
}

(Of course you can also stick this in a useEffect... but is there any reason you want to wait for React to finish rendering before you reload?)

olivarra1
  • 3,269
  • 3
  • 23
  • 34