Home > Software engineering >  React Native values are not updating correctly
React Native values are not updating correctly

Time:08-17

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.

  1. I press a button which makes midiLearnEnabled true

  2. 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

  3. I press a button which makes midiLearnEnabled true

  4. 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>

Edit priceless-leakey-hq6dlz

  • Related