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