Reputation: 6055
Is there a way to force the initial state on a page (in a component) when the page was reached via the browsers "history back" button ?
Now I'd like my page to have it's initial state, not the changed state.
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Try state</title></head>
<body>
<script>
// (You can check window.state in the DEV console)
window.state = 'initial state';
</script>
<p id="state-display">static content</p>
<button onclick="state = 'changed state'; document.getElementById('state-display').innerHTML = state;">change state</button>
</body>
</html>
I am changing pages by calling window.location.href = url
, and at the same time
I set a React state which results in displaying a loading ...
info until
the new url is loaded.
I would expect, when clicking "back", that the previous page would be loaded with its initial state again, but apparently the browser loads the last state that it has seen when the page was left ?
E.g.
isLoading
and call window.location.href = pageB
,isLoading
again instead of the expected initial state, which it would be when visiting
page A via a link or the address bar.Example:
import React from 'react';
import { createRoot } from 'react-dom/client';
// -- just some test state
const getNextState = (function(){
const values = [ 'cat', 'dog', 'fish', 'bird', 'kangaroo' ];
let index = 0;
return function(){
const current = index;
index = index < values.length - 1 ? index + 1 : 0;
return values[ current ];
};
})();
// --
function App() {
const [ state, setState ] = React.useState(() => getNextState() );
// --
// can't set state here, because `useEffect` hook is
// not (always) called when clicking on "back" button
// --
React.useEffect(() => {
console.log('mounted');
}, []);
// -- set state and change url
const goToPage = function( page ){
setState( '...loading' );
window.location.href = page;
};
return <div>
<h1>{ window.location.search === '?page2' ? 'Page 2' : 'Page 1' }</h1>
<p>{ state }</p>
<button onClick={ () => { goToPage('/?page1'); } }>go to page 1</button>
<button onClick={ () => { goToPage('/?page2'); } }>go to page 2</button>
<button onClick={ () => { setState( getNextState() ); } }>change state</button>
</div>;
}
// --
const root = createRoot(
document.getElementById('root')!
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Note 1): This apparently only happens in a production build (e.g. yarn build
, yarn start
).
Note 2): Chrome and Firefox seem to behave in the same way here, but this is a simplified example, and in my real app, where I use Redux and NextJs, this problem is only reliably reproducible in Chrome.
Note 3): I'm open for suggestions to change my routing,
but note that in some cases I have statically pre-rendered pages
and need to do a redirect in a middleware.ts
, so I can't just use client side routing.
Apparently no hooks (like useEffect
) are executed when clicking on "history back".
Not even the DOMContentLoaded
event is fired.
Apparently this behavior is not consistent. Right now Chrome doesn't show this problem anymore at my computer. Firefox still does.
Upvotes: 0
Views: 148