osh*_*ell 10 javascript safari reactjs preact
componentDidMount()在Safari中返回时,即使从未卸载过组件,React 16触发器也是如此。如何知道何时安装?
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>;
}
}
Run Code Online (Sandbox Code Playgroud)
Safari使用bfcache。如果返回,它将从缓存中获取最后一页。
当使用react 15.3或preact之类的库时,离开页面不会触发componentWillUnmount,返回页面也不会触发componentDidMount。
此行为会导致多个问题-例如,loading在重定向之前将页面状态设置为时。如果用户返回,则状态仍设置为loading,您甚至无法使用来重置状态componentDidMount,因为它永远不会触发。
有一种解决方案,使用onpageshow,但是由于它仅触发一次,因此您必须使用来重新加载整个页面window.location.reload()。这也是反应无法依赖此解决方案的原因。
我不知道 React 16 究竟是如何调用 mount 的,但它是一个完全不同的引擎,所以它可能是故意的,也可能不是。您可以做的一件事是在重定向之前安排状态重置,如下所示:
<html>
<head>
<script
crossorigin
src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.js"
></script>
<script
crossorigin
src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.js"
></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class Foo extends React.Component {
state = {
loading: false
};
componentDidMount() {
console.log("mounted");
}
leave() {
this.setState({
loading: true
});
setTimeout(() => {
this.setupReset();
window.location.href = "https://github.com";
}, 2000);
}
setupReset() {
let interval = setInterval(() => {
if (
!!window.performance &&
window.performance.navigation.type === 2
) {
clearInterval(interval);
console.log('reseting');
this.setState({ loading: false });
}
},500);
}
render() {
return this.state.loading ? (
<div>loading...</div>
) : (
<button onClick={this.leave.bind(this)}>leave</button>
);
}
}
ReactDOM.render(<Foo />, document.getElementById("app"));
</script>
</body>
</html>Run Code Online (Sandbox Code Playgroud)
然后当您返回时,执行会恢复,并且可以检测它是否来自历史记录并重置状态。
您实际上可以第一次在 componentDidMount 上设置此重置机制。
| 归档时间: |
|
| 查看次数: |
354 次 |
| 最近记录: |