Reputation: 36179
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
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
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
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
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