Aquí hay un ejemplo:
function Page() { const [a, setA] = React.useState(0); useEffect(() => { const interval = setInterval(() => { console.log(a) }, 2000) return () => clearInterval(interval) }, []); return ( <div> <span>{a}</span> <button onClick={() => setA(Math.random())}>button</button> </div> ); } El invertal siempre registra 0 a pesar de que la variable de estado de conteo en realidad se incrementó al hacer clic en el botón varias veces.
Y mucha gente dice que esto se debe a que la función de intervalo captura a archivo . Pero realmente no puedo entenderlo. Cuando no se puede encontrar una variable en el entorno actual, se resolverá como principal (o global).
Y mira este ejemplo en contraste:
function Page() { let a = 0; useEffect(() => { const interval = setInterval(() => { console.log(a) }, 2000) return () => clearInterval(interval) }, []); return ( <div> <button onClick={() => a = Math.random()}>button</button> </div> ); } Este es un ejemplo obvio para mi expresión. El cierre del intervalo captura la variable exterior a . Registrará el valor nuevo a medida que cambie.
Entonces, ¿cómo reaccionar useEffect implementar esta función?
Como mi punto de vista (un mal pseudocódigo):
const hooks = []; function useState(val) { let state = hooks[0] || val; hooks[0] = state; function setVal(v) { state = v; hooks[0] = state; } return [state, setVal]; } let cleanup = null; function useEffect(callback) { if (cleanup) cleanup() cleanup = callback(); } function Foo() { const [count, setCount] = useState(0); useEffect(() => { setTimeout(() => { console.log(count)}, 1000); }) return setCount; } var setCount = Foo(); // log 0 setCount(1); Foo(); // log 1Pero esta no es la forma en que se implementó la reacción. Entonces, ¿cómo reaccionar implementar esto?
Cada vez que se renderiza el componente, se llama a la función.
Primero se asigna un valor a a . Este es 0 (la primera vez) o el valor actual del estado (en tiempos subsiguientes).
const [a, setA] = React.useState(0); Luego hay un gancho useEffect . Esto requiere dos argumentos. Una función y una matriz de dependencia.
La función se llamará cada vez que cambien los valores en la matriz de dependencia.
En su ejemplo, la matriz de dependencia es [] . Así que los valores nunca cambian. Esto significa que la función solo se llamará en el primer renderizado .
Durante el primer render, la función a la que llamó. El valor de a es 0 .
La función pasa una función a setInterval . Esta función lee a . Se ha cerrado sobre a variable del primer renderizado .
En versiones posteriores de la función, habrá a nueva variable a (perteneciente a esta llamada a la función) a la que se le asigna cualquier valor que esté en el estado. Sin embargo, el gancho de efecto no vuelve a ejecutarse y el intervalo existente todavía está mirando la variable a original.
En su segundo ejemplo, está mutando el valor de a variable original (que es la variable sobre la que se ha cerrado el intervalo).