Primero que nada - ¡Feliz viernes!
Solo vine aquí para ver si alguien tenía alguna información sobre un problema que estoy viendo en mi aplicación ReactJs. Así que tengo un componente funcional renderViews y en ese componente funcional, hay múltiples vistas para renderizar. Luego, dentro de renderViews , tengo otro componente funcional carDetailsView e intento hacer una llamada a una API cuando aparece ese componente en particular (como un modal). requestCarsDetails() solo debe llamarse cuando aparece ese componente, por eso anidé un gancho useEffect en carDetailsView . Pero eso causa un problema:
Renderizó más ganchos que durante el render anterior
.Consulte el código a continuación:
const renderViews = () = > { useEffect(()=> { requestCarInfos() .then((res) => { setCars(cars); }); }, []); const carDetailsView = () => { useEffect(() => { requestCarDetails() .then((res) => { setDetails(res.details); }); }, []); return (<div>carDetailsView</div>) } return (<div>{determineView()}</div>) }El useEffect que se usa en el nivel superior funciona bien. El problema solo apareció después de que agregué el segundo useEffect que está en carDetailsView. Cualquier ayuda o consejo es apreciado. ¡Gracias!
Es una regla de ganchos.
https://reactjs.org/docs/hooks-rules.html
Solo ganchos de llamada en el nivel superior
No llame a Hooks dentro de bucles, condiciones o funciones anidadas. En su lugar, siempre use Hooks en el nivel superior de su función React, antes de cualquier retorno anticipado. Al seguir esta regla, te aseguras de que los ganchos se llamen en el mismo orden cada vez que se represente un componente. Eso es lo que le permite a React preservar correctamente el estado de los Hooks entre múltiples llamadas useState y useEffect.
React se basa en el orden en que se llaman los Hooks.
Siempre que el orden de las llamadas Hook sea el mismo entre renders, React puede asociar algún estado local con cada uno de ellos. si colocamos una llamada Hook dentro de una condición, podemos omitir el Hook durante el renderizado, el orden de las llamadas Hook se vuelve diferente:
React no sabría qué devolver para la segunda llamada useState Hook. React esperaba que la segunda llamada Hook en este componente correspondiera al efecto persistForm, al igual que durante el renderizado anterior, pero ya no es así. A partir de ese momento, cada siguiente llamada de Hook después de la que omitimos también cambiaría de uno en uno, lo que generaría errores.
Esta es la razón por la cual Hooks debe llamarse en el nivel superior de nuestros componentes. Si queremos ejecutar un efecto condicionalmente, podemos poner esa condición dentro de nuestro Hook:
use la pelusa https://www.npmjs.com/package/eslint-plugin-react-hooks
esta es una advertencia sobre el uso de componentes funcionales, en cada render todo lo que está dentro del componente funcional se ejecuta. por lo tanto, react necesita mantener la lista de todos los ganchos que se definieron cuando se creó el componente. Piense en ello como una matriz.
en cada procesamiento, useState devolverá el valor por usted. si entiendes esto, entenderás lo que también significa estado obsoleto. (Puede ocurrir un estado obsoleto cuando se producen cierres dentro de estos componentes)
¿Algo como eso?
const CarDetailsView = () => { React.useEffect(() => { console.log("Running CarDetailsView useEffect...") ; },[]); return( <div>I amCarDetailsView</div> ); }; const Views = () => { const [showCarDetails,setShowCarDetails] = React.useState(false); const toggleCarDetails = () => setShowCarDetails(!showCarDetails); React.useEffect(() => { console.log("Running Views useEffect...") ; },[]); return( <div> <div>I am Views</div> <button onClick={toggleCarDetails}>Toggle car details</button> {showCarDetails && <CarDetailsView/>} </div> ); }; const App = () => { return(<Views/>); }; ReactDOM.render(<App/>,document.getElementById("root")); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script> <div id="root"/>