【问题标题】:Forcing a page reload using React hooks when clicking back button on Safari单击 Safari 上的后退按钮时使用 React 挂钩强制页面重新加载
【发布时间】: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 上单击后退按钮时重新加载前一页,而不仅仅是从缓存中提取。

【问题讨论】:

标签: reactjs safari


【解决方案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 完成渲染再重新加载?)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-24
    • 2012-11-14
    • 2020-05-02
    • 2012-02-22
    • 2014-03-30
    • 2013-10-13
    • 1970-01-01
    相关资源
    最近更新 更多