Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

99
Views
Props ain't updating on event listener callback function

Callback function props.updateOrder() supposed to update props.index. In following code-block i've used this function but it dosent update the index. In the same component when using it in a onclick function it does. What am it doing wrong here?

const [image, setImage] = useState(polygons.polygonDefaultRight);

useEffect(() => {
    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);
    return () => {
        window.removeEventListener("keydown", handleKeyDown);
        window.removeEventListener("keyup", handleKeyUp);
    };
}, []);

const handleKeyUp = (e) => {
    const keys = {
        39: () => {
            e.preventDefault();
            setImage(polygons.polygonDefaultRight);
            props.updateOrder(props.orders, props.index, 'next');
            console.log('Right', props.index);
        }
    };

    if (keys[e.keyCode]) {
        keys[e.keyCode]();
    }
};

const handleKeyDown = (e) => {
    const keys = {
        39: () => {
            e.preventDefault();
            setImage(polygons.polygonHoverRight);
        }
    };

    if (keys[e.keyCode]) {
        keys[e.keyCode]();
    }
};
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

By only adding listeners on mount you create a closure over all the variables used in the handler function. For the setState() calls this can be worked around by passing a callback setState(prev => mutate(prev)), but the rest are stuck.

You can avoid this by simply adding relevant dependencies to the useEffect dependency array which will cleanup and then re-attach the listeners with updated handler functions.

In the below snippet the right arrow displays the closure over the initial state value, while the left arrow doesn't.

const { useState, useEffect } = React;

function App() {
  const [ state, setState ] = useState(0);

  // Closure
  useEffect(() => {
    document.addEventListener("keyup", handleKeyUpClosure);
    return () => {
      document.removeEventListener("keyup", handleKeyUpClosure);
    };
  }, []);

  const handleKeyUpClosure = (e) => {
    if (e.keyCode === 39) {
      setState(s => s + 1);
      console.clear();
      console.log('Closure: ', state); // always logs 0
    }
  };

  // No closure
  useEffect(() => {
    document.addEventListener("keyup", handleKeyUp);
    return () => {
      document.removeEventListener("keyup", handleKeyUp);
    };
  }, [ state ]);

  const handleKeyUp = (e) => {
    if (e.keyCode === 37) {
      setState(s => s - 1);
      console.clear();
      console.log('No closure: ', state); // logs state of current render cycle (before update).
    }
  };

  return (
    <div>
      <p>State: {state}</p>
      <p>press right arrow to increment and left arrow to decrement.</p>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>

<div id='root'></div>

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!