单击 Safari 上的后退按钮时使用 React 挂钩强制页面重新加载
Posted
技术标签:
【中文标题】单击 Safari 上的后退按钮时使用 React 挂钩强制页面重新加载【英文标题】:Forcing a page reload using React hooks when clicking back button on Safari 【发布时间】:2021-06-25 15:19:33 【问题描述】:我想强制重新加载页面(即使在使用后退按钮导航时),因为在 Safari 浏览器中,Safari 会加载页面的缓存版本,这不是我们想要的。
使用 React Hooks,我可以在 useEffect
中做到这一点。
function MyComponent()
useEffect(() =>
if (typeof window != 'undefined')
window.onpageshow = event =>
if (event.persisted)
window.location.reload()
, [])
return (<div>My Page Content</div>)
我的问题是:这样做时,是否会重复调用重新加载,因为重新加载会触发组件的重新渲染和重新安装,这反过来会调用 useEffect,然后调用 reload 然后进入这个无限循环?
另一种方法是模仿 React 类 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>)
但是,我也有同样的问题。强制重新加载是否让我陷入组件不断重新渲染、重新安装以及一遍又一遍调用重新加载的情况?
最终,我希望在 Safari 上单击后退按钮时重新加载前一页,而不仅仅是从缓存中提取。
【问题讨论】:
这能回答你的问题吗? How can I force a component to re-render with hooks in React? 【参考方案1】:是的,在这两种情况下,如果组件在启动时呈现,我希望页面进入重新加载页面的无限循环。
React 钩子没有任何类型的持久性:它们对您创建的组件实例是有状态的,并且在组件卸载(或页面卸载)时被完全删除
作为建议,我认为您不需要在 React 组件中执行此操作...它只是您想要不时运行的脚本。
这个脚本的实现可以是任何你想要的,但我想到了两个例子:
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');
这将始终只刷新一次页面。或者您可以使用时间戳:
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();
(当然你也可以把它放在 useEffect 中……但是你有什么理由要等待 React 完成渲染再重新加载?)
【讨论】:
以上是关于单击 Safari 上的后退按钮时使用 React 挂钩强制页面重新加载的主要内容,如果未能解决你的问题,请参考以下文章
单击链接时React Router V5不渲染路由,但后退和前进按钮有效?
当我单击 react-native-video 播放器中的硬件后退按钮时如何锁定 LandScape 模式?