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/

 

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