I am struggling to understand why setState in this case is not able to update state object. Below is a simple example of my issue.
class Temp extends Component<TempProps, TempState> {
constructor(props: TempProps) {
super(props);
this.state = { 1: "apple", 2: "banana", 3: "pineapple" };
}
onBtnClick = () => {
this.setState(
(prevState) => {
const newState = { ...prevState };
delete newState["2"];
console.log(newState); //{ 1: "apple", 3: "pineapple" }
console.log(newState === prevState); //false
return newState;
},
() => {
console.log(this.state); //{ 1: "apple", 2: "banana", 3: "pineapple" }
}
);
};
render() {
return (
<button onClick={this.onBtnClick}>click me</button>
);
}
}
export default Temp;
Why setState() in onBtnClick() is not able to update the state object, even though prevState===newState is false? I'm so confused... thanks a lot for the comments!
CodePudding user response:
The issue is that this.setState() performs a merge of current state and supplied value. So that the new state is like this newState = { ...oldState, ...suppliedValue }. This means that any properties omitted in the new argument will be left unchanged. That's why you could call setState({ b: 22 }) on a state currently having { a: 11, b: 12 } and the new state would be a merge of the supplied value and old value: {a: 11, b: 22}. The fact that you omitted the property: a in the supplied value won't delete it from the final state.
So the only workarounds that I know of are:
- Assign a nullish value to the property you want to delete, like
nullorundefined. This is ugly, but might serve for your needs. For eg,this.setState(prevState => ({ ...prevState, b: undefined })) - Don't assign your app's state directly to this.setState but to a nested property. Something like:
. . .
constructor(props: TempProps) {
super(props);
this.state = { appState: { 1: "apple", 2: "banana", 3: "pineapple" } };
}
. . .
onBtnClick = () => {
this.setState(
(prevState) => {
const newState = { ...(prevState.appState) };
delete newState["2"];
console.log(newState); //{ 1: "apple", 3: "pineapple" }
console.log(newState === prevState); //false
return { appState: newState };
},
() => {
console.log(this.state); //{ 1: "apple", 3: "pineapple" }
}
);
};
. . .
CodePudding user response:
You can compare two object like this.
JSON.stringify(Object A) === JSON.stringify(Object B)
