【工作笔记】如何处理react中的渲染异常

我们知道,在使用 react 渲染页面的时候,如果某个子组件发生了错误,将会造成整个页面的白屏:

// page 组件,代表整个页面
class page extends React.Component {
  // 如果 Component1 渲染失败,将会导致整个 page 组件渲染失败
  render() {
    return (
      <div>
        <Component1></Component1>
        <Component2></Component2>
        <Component3></Component3>
      </div>
    )
  }
}

这样就会造成一个问题,有些子组件并没有那么重要,是否能够渲染出来,都不应该影响到整个页面。

为了解决这个问题,react 16 中提供了 componentDidCatch 方法,用于捕获组件中的渲染异常,这样当某个组件挂掉的时候,我们可以做针对性的处理,不至于整个页面瘫痪掉。

componentDidCatch的使用方式

react 官方提供了一个示例:demo

包装组件问题

从上面的示例可以得知,我们要想处理某个组件的渲染异常,需要做两件事,首先申明一个错误处理组件:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  componentDidCatch(error, info) {
    // Display fallback UI
    this.setState({ hasError: true });
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

然后包装我们需要处理的组件:

<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

一旦使用了这种包装方式,我们必须人工判断哪些组件应该做错误处理,哪些组件可以不做错误处理,这使得我们的业务代码里会混入很多错误处理的非业务代码:

<ErrorBoundary>
  <A>
    <B></B>
    <ErrorBoundary>
      <C></C>
    </ErrorBoundary>
    <D><E></E></D>
  </A>
</ErrorBoundary>

是否可以让我们编程的时候,能够专注于业务,摆脱这种包装代码呢?我们可以尝试下面的方式。

重写 React.createElement

我们可以通过重写 React.createElement ,将代码中的每个组件都包装一下:

const rc = React.createElement
React.createElement = (type, config, ...other) => {
    return rc(ErrorBoundary, keyObj, rc(type, config, ...other))
}

使用重写后的 React.createElement 效果:

<A>
  <B></B>
  <C></C>
  <D><E></E></D>
</A>

// 上面代码通过重写的 React.createElement 转化后变为:
<ErrorBoundary>
  <A>
    <ErrorBoundary><B></B></ErrorBoundary>
    <ErrorBoundary><C></C></ErrorBoundary>
    <ErrorBoundary>
      <D>
        <ErrorBoundary><E></E></ErrorBoundary>
      </D>
    </ErrorBoundary>
  </A>
</ErrorBoundary>

这样就可以统一处理渲染异常,而不会侵入我们的业务代码!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 179,276评论 25 708
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 14,076评论 2 59
  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,945评论 1 18
  • 【老夏杂谈】今天不说橘子光说皮! 冬天吃橘子,正是最当季,但今天老夏不说橘子,只说说橘子皮。世间有些东西,都得越陈...
    拈花老夏阅读 537评论 0 0
  • 《我们的爱》这部剧已接近了尾声,从一开始到最后,我最心疼的是剧中的小朋友许婷婷。爸爸妈妈离婚,妈妈因为恨爸爸欺骗她...
    小七讲故事阅读 543评论 0 0

友情链接更多精彩内容