点击浏览器后退按钮时如何强制React组件恢复初始状态?
如何在通过浏览器「后退」按钮进入页面/组件时强制恢复初始状态?
最简示例
- 加载下方的HTML文件
- 修改状态
- 加载其他网站
- 点击浏览器「后退」按钮
此时希望页面恢复初始状态,而非修改后的状态。
<!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>
具体场景
我通过调用window.location.href = url切换页面,同时设置React状态以显示loading ...提示,直到新页面加载完成。
期望点击「后退」按钮时,前一页能重新加载初始状态,但浏览器似乎加载的是页面离开时的最后状态:
- 显示页面A
- 用户点击前往页面B的按钮
- 设置状态为
isLoading并调用window.location.href = pageB - 用户在页面B点击浏览器「后退」按钮回到页面A时,状态仍为
isLoading,而非通过链接或地址栏访问时的初始状态
示例代码:
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> );
注意1: 该问题仅在生产构建(如yarn build、yarn start)中出现。
注意2: 此简化示例中Chrome和Firefox表现一致,但在使用Redux和NextJs的实际项目中,仅在Chrome中能稳定复现该问题。
注意3: 我接受路由修改建议,但部分页面为静态预渲染,需在middleware.ts中做重定向,无法仅使用客户端路由。
无效方案
点击「后退」按钮时,似乎不会执行任何hooks(如useEffect),甚至不会触发DOMContentLoaded事件。
更新
该行为并不一致,目前我的Chrome已不再出现此问题,但Firefox仍存在。
内容的提问来源于stack exchange,提问作者kca
相关产品推荐
相关产品推荐

