请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

【3-3作业】异步组件加载失败之后的重试方法

正在回答 回答被采纳积分+3

1回答

茵风泳月 2019-05-21 12:47:53

同学你好,其实不用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造成的,避免无谓的重复加载异步组件。

祝您学习愉快!

3 回复 有任何疑惑可以回复我~
  • 老师重新渲染为什么load是为true呢不是重新渲染为最初的值false吗
    回复 有任何疑惑可以回复我~ 2019-05-22 11:09:25
  • 同学你好,这个没有关系,我们使用load这个值仅仅是让页面载入之后,异步加载About的行为是受到鼠标控制的,否则页面加载后就会立即异步加载About。
    
    重试加载的时候,我们就是想让程序去立即加载About,这时候load=true就是我们想要的。你也可以先设置为false,然后还需要点击按钮才能让load=true,多了一步。
    回复 有任何疑惑可以回复我~ 2019-05-22 13:43:57
  • 了解了老师,那一般情况加载失败以后,lazy封装了一个Promise来加载的组件是不是都失效了,都要在重新加载的时候重新构造这个Promise呢?
    回复 有任何疑惑可以回复我~ 2019-05-22 15:07:31
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信