Escribí un React simple para probar cómo se renderiza React
import ReactDOM from 'react-dom'; import React, { useState, useEffect } from 'react'; const App = (props) => { // State const [trackIndex, setTrackIndex] = useState(1); const [trackProgress, setTrackProgress] = useState(0); const clickHandler = () =>{ setTrackIndex((trackIndex)=>trackIndex+1) } useEffect(() => { console.log("effect; trackIndex=",trackIndex) console.log("effect; trackProgress=",trackProgress) if(trackIndex<5){ console.log("set trackProgress") setTrackProgress(trackIndex) } }); console.log("render") return ( <div> <p>{trackIndex}</p> <p>{trackProgress}</p> <button onClick={clickHandler}>Click me</button> </div> ); }; ReactDOM.render( <App />, document.getElementById('root') );La siguiente es la salida de la consola:
render effect; trackIndex= 1 effect; trackProgress= 0 set trackProgress render effect; trackIndex= 1 effect; trackProgress= 1 set trackProgress renderParece que React se procesa tres veces antes de hacer clic en el botón. La última representación realmente me confunde. ¿Alguien podría explicarme por qué ocurre este renderizado y por qué no se ejecuta ningún efecto después de este renderizado? Gracias de antemano
Prácticamente estás haciendo un bucle infinito, pero React te salva. El primer registro de render es el procesamiento inicial, luego se ejecuta useEffect y su componente se vuelve a procesar, lo que lleva al segundo registro de render y al primer effect; ... registro. Ahora se ejecuta un segundo useEffect de uso. Sin embargo, el valor de trackIndex no ha cambiado, por lo que su declaración if se evaluará como verdadera y actualizará trackProgress con el mismo estado/valor (1). Esto lleva a otro renderizado y al tercer registro de render . Ahora, pensaría que se ejecutaría un tercer useEffect , pero React es lo suficientemente inteligente como para saber cuándo el estado no ha cambiado y, por lo tanto, no ejecuta el useEffect .
Agregue dependencias a su useEffect como se indicó anteriormente. Eso resolverá tu problema.
useEffect( ... , [trackIndex])Parece que su useEffect está configurando el estado con setTrackProgress en el renderizado inicial del componente. Esto se debe a que trackIndex comienza en 1 , que es inferior a 5. (visto por if(trackIndex<5) ) Tenga en cuenta que no ha proporcionado la dependencia de matriz para useEffect como segundo parámetro. De acuerdo con la documentación de reacción, esto significa que el efecto solo ocurrirá una vez después del primer renderizado inicial del componente.
Además, sugeriría agregar useCallback a su clickHandler para evitar redefinir la función para cada renderizado. (Según la documentación de reacción )