Vencovsky
Vencovsky

Reputation: 31625

Is it ok to change prevState directly in react setState?

I was answering this question and I came with an answer that I'm not sure if it's correct or not.

Is it ok to change the prevState directly?

e.g.

this.setState(prevState => {        
    for(let k in prevState.content.text){
        prevState.content.text[k].line = "changed";
    } 
    return {content: prevState.content}
}

Is this acceptable? How can I do this in the correct way?

this.setState(prevState => {   
    let changedState = {...prevState}     
    for(let k in changedState.content.text){
        changedState.content.text[k].line = "changed";
    } 
    return {content: changedState.content}
}

Should I do this? Or is there a better way of doing this?

Upvotes: 0

Views: 504

Answers (2)

Andrii Golubenko
Andrii Golubenko

Reputation: 5179

The second method is also incorrect. Because spread attributes (e.g. {...prevState}) is not a deep copy. If you compare prevState.content === changedState.content you will get true. That's why the first and second methods are wrong. You can update state like that:

this.setState(prevState => {
    const newText = {};

    Object.keys(prevState.content.text).forEach((key) => {
       newText[key] = {
           ...prevState.content.text[key],
           line: "changed"
       }
    });

    return {
        content: {
            ...prevState.content,
            text: newText
        }
    }
});

Or you could use reduce instead of forEach.

Upvotes: 2

Shridhar Sharma
Shridhar Sharma

Reputation: 2387

You can modify the prevState but then you'll not be able to track the changes in your componentDidUpdate hook, because there you'll be getting the same object in the second argument as the current state, instead of the previous state.

The second method is correct

Upvotes: 0

Related Questions