We have a heated discussion on how to update a nested state in React. Should the state be unchanged or not? What is the best practice for an elegant state statement?
Say you have a state structure that looks like this:
this.state = { numberOfStudents: "3", gradeLevel: "5", students : [ { id : "1234", firstName: "John", lastName: "Doe", email: " johndoe@mail.com " phoneNumer: "12345" }, { id : "56789", firstName: "Jane", lastName: "Doe", email: " janedoe@mail.com " phoneNumer: "56789" }, { id : "11111", firstName: "Joe", lastName: "Doe", email: " joedoe@mail.com " phoneNumer: "11111" } ] }
Then we want to update the joe doe phone number. We can do this in several ways:
mutate state + forced update for rerender
this.state.students[2].phoneNumber = "9999999"; this.forceUpdate();
mutate state + setState with mutated state
this.state.students[2].phoneNumber = "9999999"; this.setState({ students: this.state.students });
Object.assign, this still mutates the state, since newStudents is just a new reference to the same this.state object points to
const newStudents = Object.assign({}, this.state.students); newStudents[2].phoneNumber = "9999999" this.setState({ students: newStudents });
Unlimited Upgrade Advisor ( https://facebook.imtqy.com/react/docs/update.html ) + setState. This can become ugly very quickly if we have the address .street, address.city, address.zip in each student object and want to update the street.
const newStudents = React.addons.update(this.state.students, {2: {phoneNumber: {$set:"9999999"}}}); this.setState({ students: newStudents })
The final line of the response document for setState states that:
Never mutate this.state directly, since calling setState () can subsequently replace the mutation you made. Relate to this. As if it is unchanging. https://facebook.imtqy.com/react/docs/react-component.html
The docs state that we should not use forceUpdate for reerender:
Usually you should try to avoid all uses of forceUpdate () and just read .props and this.state in render () from this.
Why is this what can happen if we change state and call setState later? Under what circumstances does setState () replace the mutation we created? This is a very confusing expression. Can someone please explain the possible complication of each of the scenarios that we use above to set the state.