React16—— New render return type/Error Boundaries

New render return type

  React16之前,组件必须return时必须被一个父元素(例如div)所包裹起来,这样有时就会有增加冗余的dom结构(有讲究的前端怎么能忍)。

  于是React16便提供几种新的返回类型:

  • 数组或Fragment:可以返回多个元素
const arrayType = () => (
  [
    <li key="A">1</li>,
    <li key="B">2</li>,
    <li key="C">3</li>,
    'tips:need key and commas, string must be wrapped in quotes',
  ]
);

  或

const arrayType = () => (
  // Key is the only attribute that can be passed to Fragment
  <Fragment key="keys">
    <li key="A">1</li>
    <li key="B">2</li>
    <li key="C">3</li>
      tips:
      no need key and commas, string no need be wrapped in quotes
  </Fragment>
);
  • 字符串或数值:将返回文本节点
const stringType = () => 'hello world!';

Error Boundaries

  在React之前的版本,组件内部中的js错会导致React渲染失败。例如:后端返回一个List<Object>,假设Object有个name属性,然后使用了toLowerCase()方法。但是当name的值为null时,这将导致React渲染失败报错。React16.0引入“Error Boundary”来解决这类问题。

  Error boundaries是一个类组建,并且定义了componentDidCatch(error, info)这个新的生命周期函数,componentDidCatch可以捕获的到子组件内render和其他生命周期函数内的错误,并展示出来。

  1.创建一个ErrorBoundary组件

// ErrorBoundary
export default class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false,
      errInfo: '',
    };
  }

  componentDidCatch(error, info) {
    console.log(error, info);
    this.setState({
      hasError: true,
      errInfo: info,
    });
  }

  render() {
    const { hasError, errInfo } = this.state;
    if (hasError) {
      return (<h4>{errInfo.componentStack}</h4>);
    }
    return (
      <Fragment>
        <h4>noError!</h4>
        <div>
          {this.props.children}
        </div>
      </Fragment>
    );
  }

   2.ErrorBoundary捕获子组件render内的错误

const errorList = (props) => {
  const { list } = props;
  return (
    list.map((item, index) => (
      <ul key={index}>
        {/* error */}
        <li>{item.toLowerCase()}</li>
      </ul>
    ))
  );
};


export default class App extends React.PureComponent {
  constructor() {
    super();
    this.dataList = [
      'First item',
      'Second item',
      'Third item',
      null,
    ];
  }

  render() {
    return (
      <Fragment>
        <ErrorBoundary>
          <ErrorList
            list={this.dataList}
          />
        </ErrorBoundary>
      </Fragment>
    );
  }
}

  注意:ErrorBoundary只能捕获其子组件中的错误,而不能捕获其组件本身的错误和非子组件中的错误。例如:

<ErrorBoundary>      
  {null.toLowerCase()}
</ErrorBoundary>

3.ErrorBoundary捕获子组件生命周期内的错误

export default class errorLifecycle extends React.PureComponent {
  constructor() {
    super();
  }

  componentDidMount() {
    throw new Error('error in componentDidMount');
  }

  render() {
    return (
      <Fragment>
        hello world!
      </Fragment>
    );
  }
}  


export default class App extends React.PureComponent {
  constructor() {
    super();
  }

  render() {
    return (
      <Fragment>
        <ErrorBoundary>
          <ErrorLifeCycle />
        </ErrorBoundary>
      </Fragment>
    );
  }
}

 注意:ErrorBoundary不能捕获事件处理函数中的异常。例如:

handleClick(e) {
  try {
    ...
  } catch(err) {
    ...
  }
}

  4.当ErrorBoundary包含多个子组件时,其中任何一个子组件内部发生错误时就会被componentDidMount捕获到

  5.ErrorBoundary不支持SSR

代码示例:https://github.com/MirrorHuang/react16-demo

参考:https://reactjs.org/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章