美文网首页
【工作笔记】如何处理react中的渲染异常

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

作者: 张柳哥 | 来源:发表于2018-10-23 15:41 被阅读0次

    我们知道,在使用 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>
    

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

    相关文章

      网友评论

          本文标题:【工作笔记】如何处理react中的渲染异常

          本文链接:https://www.haomeiwen.com/subject/ttmaaftx.html