Skip to content

A note about not firing side effects in useState(prev => next) ? #2882

Description

@dxinteractive

So I ended up doing this by mistake after a wonky merge:

let Foo = (props) => {
    let [bar, setBar] = useState();
    
    let handleClick = () => {
        useState(bar => {
            let newBar = bar + 1;
            props.handleBarChange(newBar); // bad, which isn't surprising
            return newBar;
        });
    };

    return <div onClick={handleClick}>click me</div>;
};

If you fire a side effect such as calling something that sets state in a higher component from a useState updater function, you get the error "Cannot update a component from inside the function body of a different component" (but not always! It seems to depend on internal timing). This definitely seems like a bad idea when you look at it, but I couldn't find any mention in the docs that this is bad.

https://reactjs.org/docs/hooks-reference.html#functional-updates

There is the note about side effects generally on useEffect:

Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase)

But this is not in the main body of a function component, doesn't feel like a true side effect as it's still just setting state within React, and doesn't feel like it's in the render phase either.

I initially wanted to comment about this here (react/react#18178), because the general message of that thread was "don't set state of another component in a render method", and I've managed to get this error message without doing that, but the thread is locked. Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions