yangshun tay
estoy probando lo nuevo Ganchos de reacción‘s useEffect
API y parece seguir ejecutándose para siempre, ¡en un ciclo infinito! Sólo quiero la devolución de llamada en useEffect
correr una vez. Aquí está mi código de referencia:
Haga clic en “Ejecutar fragmento de código” para ver que la cadena “Ejecutar useEffect” se imprime infinitamente en la consola.
function Counter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
console.log('Run useEffect');
setCount(100);
});
return (
<div>
<p>Count: {count}</p>
</div>
);
}
ReactDOM.render(<Counter />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
yangshun tay
Esto sucede porque useEffect
se activa después de cada render, que es la invocación de la Counter()
función en este caso de componentes funcionales. cuando haces un setX
llamada devuelta de useState
en un useEffect
React renderizará ese componente nuevamente, y useEffect
se ejecutará de nuevo. Esto provoca un bucle infinito:
Counter()
→ useEffect()
→ setCount()
→ Counter()
→ useEffect()
→ … (bucle)
para hacer tu useEffect
ejecutar solo una vez, pasar una matriz vacía []
como segundo argumento, como se ve en el fragmento revisado a continuación.
La intención del segundo argumento es decirle a React cuando cambia cualquiera de los valores en el argumento de la matriz:
useEffect(() => {
setCount(100);
}, [count]); // Only re-run the effect if count changes
Puede pasar cualquier número de valores a la matriz y useEffect
solo se ejecutará cuando cambie cualquiera de los valores. Al pasar una matriz vacía, le decimos a React que no rastree ningún cambio, solo se ejecute una vez, simulando de manera efectiva componentDidMount
.
function Counter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
console.log('Run useEffect');
setCount(100);
}, []);
return (
<div>
<p>Count: {count}</p>
</div>
);
}
ReactDOM.render(<Counter />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
Leer más sobre efecto de uso.
-
Esta es la solución, sin embargo, si está utilizando el
react-hooks
complemento eslint. Esto sería señalado por elexhaustive-deps
regla. Parece que la solución correcta es usar eluseCallback
gancho, más discusión aquí: github.com/facebook/react/issues/14920#issuecomment-471070149– Daniel Cooke
16 de abril de 2019 a las 14:39
Se está ejecutando en un bucle infinito porque no se proporciona ninguna dependencia al useEffect escrito.
Para evitar un bucle infinito al usar el gancho useEffect, asegúrese de proporcionar una matriz de dependencia que incluya todas las variables de las que depende el efecto
Por ejemplo, si solo desea el efecto para ejecutarse una vez cuando el componente se montapuede pasar una matriz de dependencia vacía como esta:
useEffect(() => {
// effect code here
}, [])
Si desea que el efecto se ejecute siempre que una variable específica cambiapuede incluir esa variable en la matriz de dependencia:
const [count, setCount] = useState(0);
useEffect(() => {
// effect code here
}, [count])