【发布时间】:2019-10-09 01:40:31
【问题描述】:
React 16 在返回 Safari 时触发 componentDidMount(),即使组件从未卸载。 react如何知道何时挂载?
class Foo extends React.Component {
state = {
loading: false
}
componentDidMount() {
// when going back in safari
// triggers in react 16, but not in 15.3 or preact
console.log('mounted');
}
componentWillUnmount() {
// will never trigger
console.log('will unmount');
}
leave() {
this.setState({
loading: true
});
setTimeout(() => {
window.location.href = 'https://github.com/';
}, 2000);
}
render() {
return this.state.loading ? <div>loading...</div> : <button onClick={this.leave.bind(this)}>leave</button>;
}
}
背景
Safari 使用 bfcache。如果您返回,它会从缓存中取出最后一页。
使用react 15.3或者preact等库时,离开页面不会触发componentWillUnmount,返回也不会触发componentDidMount。
此行为会导致几个问题 - 例如,当您在重定向之前将页面状态设置为 loading。如果用户返回,状态仍然设置为正在加载,您甚至无法使用 componentDidMount 重置状态,因为它永远不会触发。
有一个solution,使用onpageshow,但由于它是only triggers one time,你必须使用window.location.reload()重新加载整个页面。 这也是 react 不能依赖这个解决方案的原因。
【问题讨论】:
-
你在使用 React 路由器吗? SPA 通过使用浏览器暴露历史 API 的 history.push/pop 来处理前进/后退
-
否 - 重定向到另一个页面。我正在使用 preact 并想弄清楚 react 是如何做到最终使用此功能的。
-
显然它已知的 Safari 页面缓存限制:webkit.org/blog/427/webkit-page-cache-i-the-basics 你可能想进一步探索他们的文档,因为我确信他们可能已经有了解决方案,因为它在 2009 年实施,它似乎基于发布日期。
-
我阅读了这些文章,他们没有提供更多信息。
-
gist.github.com/oshell/bb1b3eec49a98cf6d59cef44806f0fa6 只需使用它并将 react cdn 链接替换为 15.3
标签: javascript reactjs safari preact