Se supone que la función de devolución de llamada props.updateOrder() actualiza props.index . En el siguiente bloque de código, he usado esta función pero no actualiza el índice. En el mismo componente cuando se usa en una función onclick lo hace. ¿Qué estoy haciendo mal aquí?
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](); } };Al agregar solo oyentes en el montaje, crea un cierre sobre todas las variables utilizadas en la función del controlador. Para las llamadas a setState() , esto se puede solucionar pasando una devolución de llamada setState(prev => mutate(prev)) , pero el resto está atascado.
Puede evitar esto simplemente agregando dependencias relevantes a la matriz de dependencias useEffect que limpiará y luego volverá a conectar los oyentes con funciones de controlador actualizadas.
En el siguiente fragmento, la flecha derecha muestra el cierre sobre el valor del estado inicial, mientras que la flecha izquierda no.
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>