I have a function, which is executed upon every change of an input form. It changes a state variable (foo, bar) and executes a function (_validate()) which in turn relies on foo and bar to set another state variable, valid.
const [foo, setFoo] = useState(null);
const [bar, setBar] = useState(null);
const [valid, setValid] = useState(false);
...
const _validate = () => {
console.log(foo); // this renders previous value
console.log(bar); // this renders previous value
if(foo.length !== 0) {
setValid(true);
} else {
setValid(false);
}
}
const _onChange = (origin, val) => {
if(origin === 'sth') {
setFoo(val);
_validate();
if(valid) {
// do sth
}
} else {
setBar(val);
_validate();
if(valid) {
// do sth
}
}
...
}
console.log(foo, bar); // this renders current value
render() {
...
}
If I do a console.log() in validate(), the state variables fooand bar are not the current ones, which are set after the _onChange() is called. They are the old, previous ones. Only after executing _onChange() again, the value is updated. But not with the current one, but with the previous one, which I would have expected after the first _onChange(). Note that the console.log(foo, bar); just before the render logs the expected, current values. So there is a delay of "one _onChange() in the state variables foo and bar in validate().
What could be the reason for that?
This is part is not right:
setFoo(val); // setFoo will not change the `foo` until the next render.
_validate();
Can you pass the values directly into the _validate function?
const _validate = (foo, bar) => {
console.log(foo); // this renders previous value
console.log(bar); // this renders previous value
if(foo.length !== 0) {
setValid(true);
} else {
setValid(false);
}
}
Then pass the values in with _validate(foo, bar);.
Another approach would be to put the validate func in an effect:
useEffect(() => {
if(foo.length !== 0) {
setValid(true);
} else {
setValid(false);
}
}
}, [foo, bar]);