question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using both getDerivedStateFromError and getDerivedStateFromProps can be a foot gun

See original GitHub issue

Do you want to request a feature or report a bug?

Feature

What is the current behavior?

If componentDidCatch and/or getDerivedStateFromError put the component in a state that avoids the cause of the error, and getDerivedStateFromProps reverts that state change, the error boundary will (obviously) fail to avert disaster.

https://codesandbox.io/s/pj0lwxk15j

It sounds very obvious when simplified like this, but when my team updated to React 16.5.x (and 16.6.0), suddenly this started happening for us. So something changed internally, but it’s hard to pinpoint what. Unfortunately I haven’t been able to create a small repro for that specific case that works in 16.4.2 but not 16.5.0 – so I’m making this issue about avoiding the cause in the first place.

What is the expected behavior?

Naively, my thinking is that because errors are more exceptional, let the state from error handlers take precedence. Probably there’s a reason why this can’t happen so a warning of some kind when this can happen would be nice. Two ways to do this comes to mind:

  1. Cross-check that keys in state from getDerivedStateFromProps or setState in componentDidCatch don’t collide with getDerivedStateFromError (sounds a bit far fetched?)
  2. Be more explicit in documentation for error boundaries about how getDerivedStateFromProps will run last so that a developer can consider this case

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

16.5.0 and up (16.4.2 behaves a bit differently – see above), all platforms/browsers.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:1
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
blixtcommented, Nov 4, 2018

Fair enough, it should definitely rely on what changes. Given the following scenario, what’s the correct way to set this.state.error to null when this.props.children changes (eg a property change)?

static getDerivedStateFromError(error) {
    return { error };
}

render() {
    if (this.state.error) {
        // Child component is in error state, show red box.
        return <RedBox />;
    }
    return this.props.children;
}

Here’s a sandbox: https://codesandbox.io/s/035nw47kkp

(This indicates a bug in the child component, but it’s a component out of our control and our UI will need to handle it and for good user experience recover once the component has been replaced or updated to work again.)

The options I can think of are:

  • Find every place that the error boundary is used and imperatively tell it to reset its error before rendering (since if there’s an error the setState will only happen once at this level, even as the component renders twice to recover from the error).
  • Rely on the user to press a “Retry” button in the error boundary.
  • Compare the this.props.children value that the component had upon error with the current value upon render and only show the error if it’s identity equal to the erroring this.props.children.
  • Some other way to attempt a re-render (eg by resetting error) when something further up the stack changes to probe this.props.children for potential errors and either recover from or retain the error state.
0reactions
tonypeecommented, Jan 6, 2022

I would like to have the componentDidCatch cause an error toast message to occur, but have the application continue rendering. Is it possible to resume the render? I understand that i will need to resolve the state issues myself

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why use getDerivedStateFromProps when you have ...
getDerivedStateFromProps is called both on initial mounting and on re-rendering of the component, so you can use it instead of creating ...
Read more >
1- shouldComponentUpdate(nextProps, nextState) - HackMD
getDerivedStateFromProps () returns an object to update state in response to prop changes. It can return a null if there is no change...
Read more >
Method 1: static getDerivedStateFromProps - Educative.io
In this lesson, we'll discuss a React lifecycle method in which we use state and render objects according to our example's requirement.
Read more >
You Probably Don't Need Derived State – React Blog
React 16.4 included a bugfix for getDerivedStateFromProps which caused some ... All problems with derived state that we have seen can be ...
Read more >
Lifecycle, state, getDerivedStateFromProps and Hooks - Medium
A React component is a reusable piece of code receiving props to communicate (interface) with the outside world, may have states for the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found