getDerivedStateFromError和componentDidCatch之间的区别是什么

Tom*_*zyk 27 javascript reactjs

我从这里了解到:

componentDidCatch:

  • 总是在浏览器中调用
  • 在DOM已经更新的"提交阶段"期间调用
  • 应该用于错误报告之类的东西

getDerivedStateFromError:

  • 在服务器端呈现期间也会调用
  • 当DOM尚未更新时,在"提交阶段"之前调用
  • 应该用于渲染回退UI

不过,我对某些事情感到有些困惑:

  1. 他们都捕捉到同样类型的错误吗?或者每个生命周期都会遇到不同的错误?
  2. 我应该总是使用两者(可能在同一个"错误捕捉"组件中)吗?
  3. "使用componentDidCatch进行错误恢复并不是最佳选择,因为它会强制后备UI始终同步呈现"这有什么问题?

Est*_*ask 19

问题中的陈述大多是正确的.目前,误差界限没有在SSR支持,getDerivedStateFromErrorcomponentDidCatch不会影响到服务器端.

他们都捕捉到同样类型的错误吗?或者每个生命周期都会遇到不同的错误?

他们在不同的阶段捕获相同的错误.以前可以componentDidCatch单独使用:

  static getDerivedStateFromError() {
    return { hasError: true };
  }
Run Code Online (Sandbox Code Playgroud)

  componentDidCatch() {
    this.setState({ hasError: true });
  }
Run Code Online (Sandbox Code Playgroud)

做同样的事情,componentDidCatch在添加对异步渲染的支持之前,没有机会在服务器端得到支持ReactDOMServer.

我应该总是使用两者(可能在同一个"错误捕捉"组件中)吗?

可以使用两者.文档中的示例显示:

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    logComponentStackToMyService(info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,责任在它们之间分配.getDerivedStateFromError它是唯一有益的,即如果发生错误则更新状态,同时componentDidCatch提供副作用并且可以this在需要时访问组件实例.

"使用componentDidCatch进行错误恢复并不是最佳选择,因为它会强制后备UI始终同步呈现"这有什么问题?

新的React版本旨在实现更高效的异步呈现.正如评论中也提到的那样,同步渲染不是后备UI的一个大问题,因为它可以被视为边缘情况.


Shu*_*tri 9

在渲染期间,生命周期方法或任何子组件的构造函数中发生错误时,将同时调用这两种方法。在实现错误边界时可以使用它们

根据React文档

getDerivedStateFromError后代组件引发错误后,将调用生命周期。它接收作为参数抛出的错误,并且应返回值以更新状态。


他们都捕获相同类型的错误吗?还是每个生命周期都会捕获不同的错误?

这两个生命周期方法都将捕获相同的错误,但是这两个组件的参数都不同。

getDerivedStateFromError仅接收错误作为参数时,componentDidCatch也接收第二个参数,即info, i.e An object with a componentStack key containing information about which component threw the error.

getDerivedStateFromError()在“渲染”阶段调用,因此不允许有副作用。对于这些用例,请componentDidCatch()改用。虽然componentDidCatch也可以用于setState,但是在将来的版本中将不建议使用

componentDidCatch 应该用于副作用,例如记录错误


@Brian Vaughn通过您提供的链接详细说明了它们的用法

getDerivedStateFromError 与服务器端渲染一起使用。 componentDidCatch是提交阶段生命周期,但是服务器上没有提交阶段。getDerivedStateFromError是呈现阶段的生命周期,因此可用于启用服务器上的错误处理。

渲染阶段恢复更安全。通过进行错误恢复 componentDidCatch的过程有点麻烦,因为它依赖于错误组件下的所有内容的中间提交“ null”。这可能会导致树中更高层次的实现componentDidMount或componentDidUpdate的任何组件内部出现后续错误,并仅假定其引用为非空(因为它们始终处于非错误情况下)。

getDerivedStateFromError不会强制同步渲染。由于提交阶段生命周期中的状态更新始终是同步的,并且由于在提交阶段调用componentDidCatch,因此使用componentDidCatch进行错误恢复不是最佳方法,因为它会强制回退UI始终同步呈现。(当然,这不是一个大问题,因为错误恢复应该是一个边缘情况。)

如果发生错误,getDerivedStateFromError()将首先调用错误边界的 方法(更新状态),然后调用render()方法(以实际呈现后备UI),然后componentDidCatch(一旦后备UI已提交给DOM) 。

如果错误边界定义了其他生命周期方法(例如componentWillUpdate,componentDidUpdate),它们也将被调用,就像在其他任何渲染上一样。


“使用componentDidCatch进行错误恢复不是最佳方法,因为它强制后备UI始终同步呈现”这是怎么回事?

这意味着,在渲染后备UI的render方法之后调用componentDidCatch,这可能会导致更多问题,同时getDerivedStateFromError在渲染阶段之前更新状态,以便渲染正确的后备UI,并且不会对渲染的组件造成更多错误。新版本还针对异步渲染,这可能与当前方法有关


Ame*_*icA 6

实际上,他们都有相同的目标,但处于不同的阶段,当然,在编写ErrorBoundary组件时我使用该getDerivedStateFromError方法,因为我遵守ReactJs Docs。医生有这样一句话:

使用 staticgetDerivedStateFromError()在抛出错误后呈现后备 UI。用于componentDidCatch()记录错误信息。

当然,它有一些原因,所以我总是使用渲染后备 UIgetDerivedStateFromError以及捕获信息并执行我使用的操作componentDidCatch