Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Repeated state setter callbacks when callback throws #26737

Open
farsightsoftware opened this issue Apr 28, 2023 · 2 comments
Open

Bug: Repeated state setter callbacks when callback throws #26737

farsightsoftware opened this issue Apr 28, 2023 · 2 comments
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@farsightsoftware
Copy link

It's a minor thing, but confusing: If you call a useState state setter and the callback throws, React calls the state setter callback twice more before allowing the error to propagate to the console (then twice more after that, with a development build). This obscures the nature of the error. I'd expect the callback to be called just once. This happens both with dev and prod builds of the library (though the number of calls varies), and without StrictMode.

React version: 18.2.0

Steps To Reproduce

  1. Call a state setter passing in a callback that throws

Link to code example: https://codesandbox.io/s/react-state-setter-oddity-40jgq5?file=/src/index.js (but look in the actual console, not the CodeSandbox console, it doesn't show everything).

function App() {
    const [value, setValue] = useState(0);

    const update = () => {
        console.log("calling state setter");
        setValue((v) => {
            console.log("state setter callback called");
            if (Math.random() < 1) {
                //           ^^^^ Always true, just to fool ESLint
                throw new Error("!!"); // <== Stand-in for code that throws unexpectedly
            }
            console.log("state setter callback returned");
            return v + 1;
        });
    };

    return (
        <div className="app">
            <div>Value: {value}</div>
            <input type="button" onClick={update} value="Update" />
        </div>
    );
}

The current behavior

In development, calling update causes the state setter callback to be called a total of five times: Three prior to the error being reported in the console, then twice more, with the error appearing a total of three times.

calling state setter
state setter callback called
state setter callback called
state setter callback called
Uncaught Error: !!
    at ...
state setter callback called
state setter callback called
Uncaught Error: !!
    at ...
The above error occurred in...
Uncaught Error: !!
    at ...

WIth a production build, the state setter callback is called three times, and the error reported twice (https://thenewtoys.dev/temp/react-repeating-state-setter):

calling state setter
state setter callback called
state setter callback called
state setter callback called
Error: !!
    at ...
Uncaught Error: !!
    at ...

The expected behavior

Calling update should cause the state setter callback to be called just once, and the error to be reported just once.

calling state setter
state setter called
Uncaught Error: !!
    at ...
The above error occurred in...

As I say, it's a minor thing, but the current behavior obscures the nature of the error. In my case, the error I was getting seemed to be a result of the repeated (seemingly-recursive) calls to the callback, so I was looking for a way my code could be doing that (since select isn't broken :-) ). But eventually I realized it was React doing the repeated calls.

@farsightsoftware farsightsoftware added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Apr 28, 2023
@farsightsoftware farsightsoftware changed the title Bug: Repeated Bug: Repeated state setter callbacks when callback throws Apr 28, 2023
Copy link

github-actions bot commented Apr 9, 2024

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Apr 9, 2024
@tjcrowder
Copy link

Yes, this affects us. It took hours to figure out the first time, and despite best efforts, if we have a but causing a setter to throw again there's every chance we'll fail to remember this and spend hours debugging it again (sad but true :-) ).

@github-actions github-actions bot removed the Resolution: Stale Automatically closed due to inactivity label Apr 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

2 participants