Mi función handleKeyUp no está usando ninguno de los nuevos valores en el estado. En la función, playingTrackInd siempre es igual a -1, incluso cuando el estado se ha actualizado para que playingTrackInd sea diferente.
import React, { useEffect, useRef, useState } from 'react'; import { Container } from 'react-bootstrap'; export interface Track { artist: string, title: string, uri: string, albumUrl: string, previewUrl?: string, } export default function Dashboard() { const [playingTrackInd, setPlayingTrackInd] = useState<number>(-1); const tracks = useRef<Array<Track>>([]); // add keylistener useEffect(() => { document.addEventListener('keyup', handleKeyUp); }, []); // this function always has playingTrackInd as -1, even when the state has been updated by setPlayingTrackInd function handleKeyUp(e: any) { if (e.keyCode === 39) { // right arrow pressed if (playingTrackInd === tracks.current.length - 1) { getRandomTrack(() => setPlayingTrackInd(prevInd => prevInd + 1)); } else { setPlayingTrackInd(prevInd => prevInd + 1) } } else if (e.keyCode === 37) { // left arrrow key pressed if (playingTrackInd > 0) { setPlayingTrackInd(prevInd => prevInd - 1); } } } // function that gets random track and adds it to tracks function getRandomTrack(callback?: Function) { getRandomTrackFromApi().then((track) => { tracks.current.push(track); if (callback) { callback(); } }) } // get first random track and set playingTrackInd to 0. This happens as soon as the component is loaded useEffect(() => { if (playingTrackInd === -1) { getRandomTrack(() => setPlayingTrackInd(0)); } getRandomTrack(); getRandomTrack(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( (component that depends on tracks[playingTrackInd]) ); }No puedo entender por qué playingTrackInd siempre es -1 solo en la función handleKeyUp. En todos los demás, incluida la declaración de devolución, es el valor adecuado. Gracias.
El problema radica en el siguiente efecto:
useEffect(() => { document.addEventListener('keyup', handleKeyUp); }, []); Como puede ver, está registrando handleKeyUp una vez (el efecto se activa una vez, en el montaje, porque la matriz de deps está vacía). handleKeyUp recuerda el último valor de reproducción de playingTrackInd a través de Closure ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures ). Cuando se actualiza playingTrackInd , el componente se vuelve a representar, se crea una nueva función handleKeyUp , pero ya ha registrado su handleKeyUp que recuerda el valor anterior y no está actualizando ese oyente.
Puede solucionar ese problema, por ejemplo, pasando handleKeyUp a la matriz de dependencia como se muestra a continuación:
useEffect(() => { document.addEventListener('keyup', handleKeyUp); return () => { document.removeEventListener('keyup', handleKeyUp); } }, [handleKeyUp]); No olvide eliminar el oyente antes de que se registre un nuevo oyente. La solución no es ideal, porque la función handleKeyUp se crea cada renderizado. El mismo problema existe en su segundo useEffect .
Recomiendo encarecidamente envolver sus funciones en useCallback ( https://reactjs.org/docs/hooks-reference.html#usecallback ) y pasar todas las dependencias en matrices deps. De esa manera, sus funciones no se crearán en cada renderizado, sino solo cuando cambien sus dependencias.
Otra cosa es que hay una regla eslint que lo ayudará a rastrear todas las dependencias requeridas en matrices de dependencias, verifique exhaustive-deps https://reactjs.org/docs/hooks-rules.html