I must be doing something dumb here, but after a day of trying to figure it out, I am turning here...
I have a dropdown menu for each element of an array val
which I save in the Component state:
class C extends Component {
state = { val : [ 1,2,3,4] }
...
}
where a change in each of the dropdown entries triggers this callback:
onChanged = (event, index) => {
console.log("val changed");
this.setState(state => {
const val = state.val;
val[index] = event.target.value;
return { val: val };
});
};
Now the issue is that I can't figure out how to detect this change in shouldComponentUpdate
. Specifically, when I change one of the dropdown options, I see val changed
being logged. However, in the shouldComponentUpdate
method, the nextState
and this.state
always contain the same values (and appear to be identical on comparison). So there is no way for me to detect a change in shouldComponentUpdate
. Here is the exact code I am using:
shouldComponentUpdate(nextProps, nextState) {
console.log(
"shouldComponentUpdate",
nextProps.val,
this.state.val,
nextState.val,
this.state.val === nextState.val
);
return false;
}
Before a change in one of the dropdown options, this logs something like
shouldComponentUpdate, undefined, [1, 2, 3, 4], [1, 2, 3, 4], true
If I change the first dropdown from 1
to 9
, then I see
shouldComponentUpdate, undefined, [9, 2, 3, 4], [9, 2, 3, 4], true
I expected that immediately after the change I would see
shouldComponentUpdate, undefined, [1, 2, 3, 4], [9, 2, 3, 4], true
Please tell me how I can detect a change in shouldComponentUpdate
or what idiom I should be using.
EDIT:
It was suggested that I slice
the value array in the onChanged
callback, that is, change to callback to:
onChanged = (event, index) => {
console.log("val changed");
this.setState(state => {
const val = state.val.slice();
val[index] = event.target.value;
return { val: val };
});
};
That did not fix the issue. Here is the console log before and after a change:
shouldComponentUpdate undefined (4) [1, 2, 3, 4] (4) [1, 2, 3, 4] true
val changed
shouldComponentUpdate undefined (4) [9, 2, 3, 4] (4) [9, 2, 3, 4] true
EDIT:
Crikeys I am dumb. There was a dumb return statement that was getting hit. I totally missed it. I am accepting the answer below since they are correct as the problem was stated.
That is because you are mutating the array and re use it.
Change const val = state.val;
to either
const val = [...state.val];
or
const val = state.val.slice();
to create a new array
JS arrays are passed by reference and not pass by value.
when you are doing const val = state.val;
and val[index] = event.target.value;
it is changing the state variable before setState.
example:
var a = {x: [1,2,3]}
var b = a.x
b[0] = 5 // b = [5, 2, 3] and a = {x: [5,2,3]}
You can use slice or destructuring to solve your problem.
//Slice
const val = state.val.slice()
//Destructure
const val = [...state.val]
In the above example:
var a = {x: [1,2,3]}
var b = [...a.x]
var c = a.x.slice()
b[0] = 5 //b = [5, 2, 3] and a = {x: [1,2,3]}
c[0] = 6 //b = [6, 2, 3] and a = {x: [1,2,3]}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.