what's the difference between getDerivedStateFromError and componentDidCatch

The statements in the question are mostly correct. Currently error boundaries aren't supported in SSR, getDerivedStateFromError and componentDidCatch don't affect server side.

are they both catching the same type of errors? or each lifecycle will catch the different error?

They are catching same errors but at different phases. This previously was possible with componentDidCatch alone:

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

and

  componentDidCatch() {
    this.setState({ hasError: true });
  }

do the same thing, componentDidCatch has no chances to be supported on server side until the support for asynchronous rendering will be added to ReactDOMServer.

should I always use both (in the same "error-catching" component possibly)?

You can use both. An example from the documentation shows that:

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; 
  }
}

In this case responsibilities are divided between them. getDerivedStateFromError does the only thing it is good for, i.e. updates the state if an error occurs, while componentDidCatch provides side effects and can access this component instance if needed.

"using componentDidCatch for error recovery is not optimal because it forces the fallback UI to always render synchronously" what's wrong with that?

New React releases are aimed at asynchronous rendering which is more efficient. As it was also mentioned in the comment, synchronous rendering is not a big concern for fallback UI because it can be considered edge case.


Both of these methods are called when there is an error during rendering, in a lifecycle method, or in the constructor of any child component. They can be used while implementing Error boundaries

According to the React docs

getDerivedStateFromError lifecycle is invoked after an error has been thrown by a descendant component. It receives the error that was thrown as a parameter and should return a value to update state.


are they both catching the same type of errors? or each lifecycle will catch the different error?

Both of these lifecycle methods will catch the same errors, but the arguments to both of these components are different.

While getDerivedStateFromError receives just the error as the arguments, componentDidCatch also receives the second parameter which is info, i.e An object with a componentStack key containing information about which component threw the error.

getDerivedStateFromError() is called during the “render” phase, so side-effects are not permitted. For those use cases, use componentDidCatch() instead. While componentDidCatch can also be used to setState but this will be deprecated in future releases

componentDidCatch should be used for sideEffects like logging errors


Also @Brian Vaughn has elaborated more on their usage on the link that you provide

getDerivedStateFromError works with server-side rendering. componentDidCatch is a commit phase lifecycle, but there is no commit phase on the server. getDerivedStateFromError is a render phase lifecycle, and so it can be used to enable error handling on the server.

Render phase recovery is safer. The story for error recovery via componentDidCatch is a little janky, since it relies on an intermediate commit of "null" for everything below the component that errored. This might result in subsequent errors inside of any components higher up in the tree that implement componentDidMount or componentDidUpdate and just assume that their refs will be non-null (because they always are in the non-error case).

getDerivedStateFromError doesn't force sync rendering. Because state-updates from commit phase lifecycles are always synchronous, and because componentDidCatch is called during the commit phase– using componentDidCatch for error recovery is not optimal because it forces the fallback UI to always render synchronously. (This is admittedly not a huge concern, since error recovery should be an edge case.)

In the event of an error, your error boundary's getDerivedStateFromError() method will first be called (to update state), then the render() method (to actually render the fallback UI), and then componentDidCatch (once the fallback UI has been committed to the DOM).

If your error boundary defines other lifecycle methods (e.g. componentWillUpdate, componentDidUpdate) they will also get called, just like they would on any other render.


"using componentDidCatch for error recovery is not optimal because it forces the fallback UI to always render synchronously" what's wrong with that?

what it means is that , componentDidCatch is called after the render method which renders fallback UI and that might lead to more issues while getDerivedStateFromError updates state before the render phase so that the correct fallback UI is rendered and no more errors are caused to the rendered components. Also the new releases aim at async rendering which might have issues with the current approach


Actually, Both of them have the same goal but in a different phase, definitely, for writing ErrorBoundary component I use the getDerivedStateFromError method because I obey the ReactJs Docs. the doc has this sentence:

Use static getDerivedStateFromError() to render a fallback UI after an error has been thrown. Use componentDidCatch() to log error information.

Surely, it has some reasons so for rendering fallback UI I always use getDerivedStateFromError and for catching information and do something I use componentDidCatch.