I have React project and I am trying to update the state if midiType when midiLearnEnabled is true. When I run the assignMidiCheck function to console.log the correct values are not being printed.
I press a button which makes midiLearnEnabled true
If message change from the MidiMessageContext it sets the midiType and run function to print to log. In console.log I still get 0 as the result
I press a button which makes midiLearnEnabled true
press save button which runs the same function to print to log it will show the correct midiType value. I am not sure why I can't programming print the correct value
export default Midi = () => {
// value is coming from context
const { message } = useContext(MidiMessageContext);
const [midiLearnEnabled, setMidiLearnEnabled] =
(useState < true) | (false > false);
const [midiType, setMidiType] = useState < number > 0;
useEffect(() => {
if (midiLearnEnabled) {
setMidiType(message.midiType);
setTimeout(() => {
assignMidiCheck();
}, 100);
}
}, [message]);
const assignMidiCheck = () => {
console.log(midiType);
};
return (
<Button
variant="solid"
colorScheme="secondary"
size="sm"
w={90}
onPress={() => assignMidiCheck()}
>
Save
</Button>
);
};
CodePudding user response:
The issue you had is due method in setTimeout is using closure-captured midiType
which kept old value. setMidiType will change the value on next render only, and the function will be able to read new value on next render only but it is called on "current" render.
For things like that hook useRef
is commonly used.
export const Midi = () => {
// value is coming from context
const { message } = useContext(MidiMessageContext);
const [midiLearnEnabled, setMidiLearnEnabled] = useState<true | false>(false);
const [midiType, setMidiType] = useState<number>(0);
const midiTypeRef = useRef(midiType);
// used to update midiTypeRef only
useEffect(() => {
midiTypeRef.current = midiType;
}, [midiType]);
const assignMidiCheck = () => {
console.log(midiTypeRef.current);
};
useEffect(() => {
if (!midiLearnEnabled) return;
setMidiType(message.midiType);
setTimeout(() => {
assignMidiCheck();
}, 100);
}, [message, midiLearnEnabled]);
return <button onClick={() => setMidiLearnEnabled(true)}>Save</button>;
};
Sorry for simplified <button>