错误处理

Nerv 和 React fiber 一样,支持使用 componentDidCatch 来处理组件中可能会发生的错误。

捕获组件内的错误

如下的代码在 Nerv 中使用是完全合法的:当 this.state.error 是一个假值(falsey) 时,render() 函数直接抛出异常——而这个异常会被当前组件的 componentDidCatch 捕捉到,这里使用的错误处理是把 this.state.error 设为真值。组件得以正常渲染。

  1. class BrokenRender extends Component {
  2. state = { error: null }
  3. componentDidCatch(error) {
  4. this.setState({ error })
  5. }
  6. render() {
  7. if (this.state.error) {
  8. return <span>{`Caught an error: ${this.state.error.message}.`}</span>
  9. }
  10. throw new Error('broken')
  11. }
  12. }

使用错误边界(ErrorBoundary)

如果当前组件没有设置 componentDidCatch 时,Nerv 会继续往它的父组件寻找设置了 componentDidCatch 的组件,并在该组件调用 componentDidCatch 方法处理错误。这意味着你可以设置一个错误边界(ErrorBoundary)组件来处理错误:

  1. class ErrorBoundary extends Component {
  2. state = { error: null }
  3. componentDidCatch(error) {
  4. this.setState({ error })
  5. }
  6. render() {
  7. if (this.state.error) {
  8. return <span>{`Caught an error: ${this.state.error.message}.`}</span>
  9. }
  10. return <div>{this.props.children}</div>
  11. }
  12. }
  13. class BrokenRender extends Component {
  14. componentDidMount() {
  15. throw new Error('Hello')
  16. }
  17. render() {
  18. return <span>Hello</span>
  19. }
  20. }
  21. render(
  22. <ErrorBoundary>
  23. <BrokenRender />
  24. </ErrorBoundary>,
  25. scratch
  26. )

在如上代码代码中,BrokenRender并没有错误处理方法,但是它的父组件 ErrorBoundary 可以处理错误并打印错误信息。这意味着即便 BrokenRender 崩溃了,其他组件也能正常地运行。合理地使用 ErrorBoundary 将会很好地提高开发和用户体验。

为何不使用 try/catch?

try / catch 也可以做相同的事情,但其仅能在命令式代码(imperative code)下可用:

  1. try {
  2. showButton();
  3. } catch (error) {
  4. // ...
  5. }

然而,Nerv 组件是声明式的并且具体指出 声明 什么需要被渲染:

  1. <Button />

错误边界保留了 Nerv 原生的声明性质,且其行为符合你的预期。例如,即使错误发生 componentDidUpdate 时期由某一个深层组件树中的 setState 调用引起,其仍然能够冒泡到最近的错误边界。

componentDidCatch 无法处理的错误- 事件处理- 异步代码(例如 setTimeout 或 requestAnimationFrame 回调函数)- 服务端渲染

原文: https://nervjs.github.io/docs/guides/error.html