Tomasz Mularczyk
Tomasz Mularczyk

Reputation: 36179

Can I mutate state passed to setState function?

I know I should not mutate state directly in React, but how about situation when I use function:

onSocialClick = e => {
    const id = e.target.value;
    this.setState((prevState, props) => {
        prevState[id] = !(prevState[id]);
        return prevState;
    });
};

Is it a mistake to modify passed object?

EDIT:

It turns out that most of us were wrong here. React docs state it clearly now:

state is a reference to the component state at the time the change is being applied. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from state and props

Thanks to @Tomáš Hübelbauer for pointing it out in the comment.

Upvotes: 15

Views: 3265

Answers (4)

Akshay Vijay Jain
Akshay Vijay Jain

Reputation: 15945

No, you should not mutate the prevState in updater function of setState.

Updater function has to be a pure function


The updater function is called twice. See this discussion

Check the following codesandbox and open the console of the codesandbox to see it in action.

Upvotes: 0

Fez Vrasta
Fez Vrasta

Reputation: 14825

A cleaner way would be to refer directly to the property you want do edit:

doIt = () => this.setState(({ [id]: prevValue }) => ({
  [id]: !prevValue,
}));

Upvotes: 3

Shubham Khatri
Shubham Khatri

Reputation: 281676

The way you do it is not wrong. Its perfectly okk to modify the argument and then return it. However setState with prevState argument is used when you modify the state based on the value of the prevState and it prefectly fits your scenario and a more cleaner way to handle it would be

onSocialClick = e => {
    const id = e.target.value;
    this.setState((prevState, props) => {
        return {[id] : !(prevState[id])};
    });
};

Upvotes: 0

yogi
yogi

Reputation: 1367

It is highly discouraged to mutate the state directly. Also, you are mutating the previous state and then returnning it which doesnt make much sense. If all you want is to toggle the state at state[id] then fix your code to be more like:

onSocialClick = e => {
    const id = e.target.value;
    this.setState({this.state[id]: !this.state[id});
};

Upvotes: -1

Related Questions