Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Context value not updating inside event listener in React

I am building a simple game in react. The problem is context is properly updated but the context value inside an event listener function is not updating. If I access the value outside the event function then the new updated value is rendered.

For the first keyup event the value will be 0 but for the next events, it should be a new updated value.

  const updateGame = useUpdateGame();
  const gameData = useGameData(); 
  //Assume Default gameData.board value is 0

  // Assume context value updated to 5

  useEffect(() => {
    document.addEventListener("keyup", (e) => {
      e.stopImmediatePropagation();
      console.log(gameData.board) //0
      handleKeyPress(e.key, gameData.board, updateGame);
    });
  }, []);
  console.log(gameData.board) //5

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The event listener has closed over the old value of context (think closures). You will need to keep the updated value of the context in the event listener.

This could either be done by defining the event listener everytime the context value changes or using a ref.

  1. Register and clear the event listener in the useEffect after every render when gameData changes.
const updateGame = useUpdateGame();
  const gameData = useGameData(); 

  useEffect(() => {
    let listener = (e) => {
      e.stopImmediatePropagation();
      handleKeyPress(e.key, gameData.board, updateGame);
    };

    document.addEventListener("keyup", listener);

return () => {
    document.removeEventListener("keyup", listener);
};
  }, [gameData]); //updateGame should be added here too ideally
  1. Keep a ref which mimics the value you are looking for. ref are stable containers so they will always have the correct value of the state
  const updateGame = useUpdateGame();
  const gameData = useGameData(); 
  const gameDataRef = useRef(gameData?.board ?? null);


  useEffect(() => {
    document.addEventListener("keyup", (e) => {
      e.stopImmediatePropagation();
      handleKeyPress(e.key, gameDataRef.current, updateGame);
    });
  }, []);

  useEffect(() =>{
   gameDataRef.current = gameData.board;
  },[gameData]);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading