Creé un componente React que actúa como un menú emergente para una tabla (una cuadrícula agrícola para ser exactos), lo que significa que este componente se representa cada vez que se abre una celda de la tabla y luego se desmonta/elimina cada vez que se cierra la celda.
Este componente que hice llama a useffect dentro de su efecto de uso, de modo que una vez que los datos necesarios para el componente se reciben de un GET, vuelve a representar el componente con los datos.
Código)
const myPopup = forwardRef((props, ref) => { const [componentData, setComponentData] = useState({}); useEffect(() => { fetch(`myurl.com/getdata/1`) //fetch from URL .then((response) => response.json()) .then((data) => setComponentData(data)); //set component data hook with response (should trigger re-render with response data) }, []); console.log(componentData); . . . });Cuando abro una celda de tabla por primera vez, el componente se muestra exactamente como se esperaba y la consola muestra dos cosas:
{} //from the initial state/render of component {1:'res', 2:'imm',...} //the data loaded (from the re-render after componentData is set to the FetchAPI result)Cuando abro una celda de tabla por segunda vez, lo mismo: funciona como se esperaba
Cuando abro una celda por tercera vez , mi componente se renderiza con {} (el estado inicial) y nunca se vuelve a renderizar con los datos de FetchAPI. Mirando la consola, todo lo que tengo es:
{} //re-render never occured, meaning FetchAPI never called setComponentData() with it's responseInvestigué más a fondo y parece que FetchAPI no hace ninguna llamada en esta tercera vez, ya que cuando miro nuestro servidor, no hay solicitudes entrantes después de las dos primeras (lo que explicaría por qué el componente nunca vuelve a renderizar FetchAPI no obtiene una respuesta y, por lo tanto, nunca llega a .then() para llamar a setComponentData() )
Con eso, ¿por qué FetchAPI no realiza la llamada después de la segunda? Me sorprende que esto funcione las dos primeras veces pero no después.
Cualquier ayuda sería muy apreciada, este error me ha estado volviendo loco durante algunas semanas.
Comencemos con el problema: se debe usar una referencia para pasar un componente o pasar una referencia a una variable para no volver a renderizar el componente que accede a esa variable. Deben usarse dentro de un gancho useEffect(), no al revés. Si desea pasar una función (como una función de búsqueda), pásela como accesorio. Luego, coloque la función en el enlace useEffect del componente secundario.
Ahora, para responder a su pregunta: el gancho useEffect se llama cuando se procesa el componente. Una referencia al componente no desencadenará un renderizado. Por lo tanto, solo activará useEffect en el renderizado inicial.
Haz esto en su lugar:
const ParentComponent = () => { const myFetchFunction = async url => { fetch(url) //fetch from URL .then((response) => response.json()) return( ... <myPopup initFetchFunction={myFetchFunction}/> ... ); //Or however you want to implement your component. } const myPopup = props => { const [componentData, setComponentData] = useState({}); useEffect(() => { props.initFetchFunction(`myurl.com/getdata/1`).then((data) => setComponentData(data)); }, []); useEffect(()=> { console.log(componentData); },[componentData]; . . . };