同学你好,其实不用force,我们也能触发重渲染,比如下面的代码:
let About = lazy(() => import('./About.jsx'));
class App extends Component {
state = {
load: false,
error: false,
}
// 手动触发异步组件的加载
load = () => {
this.setState({load: true});
}
// 加载失败后,点击重试
retry = () => {
this.setState({error: false});
}
// ErrorBoundary 的关键,无需再实现 componentDidCatch
static getDerivedStateFromError(e) {
return {error: e}
}
render() {
const { load, error } = this.state;
// 显然错误页
if (error) {
return (<div>
<p>{error.message}</p>
<button onClick={this.retry}>retry</button>
</div>);
}
return (
<div>
<button type="button" onClick={this.load}>load</button>
<Suspense fallback={<div>loading</div>}>
{
load && (
<About/>
)
}
</Suspense>
</div>
);
}
}
当发生错误之后,我们在错误页中提供一个重试(retry)按钮,点击后,会将error置为false,按理说React会再次渲染下面的部分,因为load=true,应该会重新加载About组件。
但是,无论你重试多少次,都一样失败,这是为什么呢?
这是因为,lazy其实封装了一个Promise来加载 About,我们知道Promise只会执行一次,一旦这个Promise失败,那么无论重新获取多少次它的结果,依然是失败的。
具体请参考 import 的原理。
那有没有办法解决呢?当然有,就是重新构造这个Promise:
{
retry = () => {
About = lazy(() => import('./About.jsx'));
this.setState({error: false});
}
}
关键在于重新生成这个About异步组件。
在实际的业务场景中,你需要识别渲染错误到底是不是由于lazy造成的,避免无谓的重复加载异步组件。
祝您学习愉快!