¿Cuál es la diferencia entre estas dos formas de pasar el componente como accesorios?
RepoMenu tal como está: <Fetch url={`https://api.github.com/users/${login}/repos`} renderSuccess={RepoMenu} />RepoMenu en una función <Fetch url={`https://api.github.com/users/${login}/repos`} renderSuccess={({ data }) => <RepoMenu data={data} />} /> RepoMenu usa internamente un enlace personalizado.
function RepoMenu({ data, onSelect = (f) => f }) { const [{ name }, prev, next] = useIterator(data); return ( <div style={{ display: "flex" }}> <button onClick={prev}><</button> <p>{name}</p> <button onClick={next}>></button> </div> ); } El uso de uno (Pasar RepoMenu tal como está) comienza a fallar, React comienza a lanzar una excepción Rendered more hooks than during the previous render.
Inicialmente pensé que no era posible usar el componente como el método 1 . Pero para probarlo más, creé un pequeño componente puro y solo traté de procesar los datos que se le pasaron.
function RepoMenuPure({ data = [], onSelect = (f) => f }) { return ( <div style={{ display: "flex" }}> <h3>There are {data.length} repos for this user</h3> </div> ); }Y cuando traté de usarlo como se muestra a continuación, funcionó en este caso.
const UserRepositories = ({ login, selectedRepo, onSelect = (f) => f }) => { return ( <Fetch url={`https://api.github.com/users/${login}/repos`} renderSuccess={RepoMenuPure} /> ); };¿Puede alguien ayudarme a explicar qué está sucediendo y qué me estoy perdiendo?
He creado una pequeña caja de arena aquí: https://codesandbox.io/s/stackoverflow-example-bqfn3e?file=/src/App.js
return renderSuccess({ data }); Su problema es que está llamando a un componente como una función. Cada vez que llame a renderSuccess (que es RepoMenu ; ahora no se considera un componente), activará su useIterator de gancho personalizado que no es válido.
Puedes consultar este documento
No llame a Hooks dentro de bucles, condiciones o funciones anidadas.
La parte de funciones anidadas es su situación actual.
Con el componente puro, estaba funcionando porque no usaste ningún gancho, por eso no ves que salga ningún error.
Para la solución, puedes hacerlo de esta manera.
import React from "react"; import { useFetch } from "./hooks/useFetch"; function Fetch({ url, loadingFallback = <div>Loading....</div>, errorFallback = <div>Some thing went wrong</div>, renderSuccess: RenderSuccess //introduce it as a component }) { const { data, error, loading } = useFetch(url); if (loading) { return loadingFallback; } if (error) { return errorFallback; } if (data) { return <RenderSuccess data={data} />; //render a component instead of executing a function } return null; } export default Fetch;En la primera opción:
renderSuccess={({ data }) => <RepoMenu data={data} />} Está diciendo que el componente Fetch espera que renderSuccess reciba una función que devuelva un Component . Si estuviera usando mecanografiado, el tipo de renderSuccess en Fetch sería algo como:
renderSuccess : (data: any) => JSX.Element // OR return the component itself renderSuccess : (data: any) => RepoMenu Y es por eso que cuando llamas a renderSuccess({ data }) dentro del componente Fetch funciona.
En la segunda opción:
renderSuccess={RepoMenu} Está diciendo que el componente Fetch espera que renderSuccess reciba el componente RepoMenu (no una función). Si estuviera usando mecanografiado, el tipo de renderSuccess en Fetch sería algo como:
renderSuccess : JSX.Element // OR the component itself renderSuccess : RepoMenuPara que esta opción funcione, debe cambiar su componente Fetch a algo como esto:
import React from "react"; import { useFetch } from "./hooks/useFetch"; function Fetch({ url, loadingFallback = <div>Loading....</div>, errorFallback = <div>Some thing went wrong</div>, renderSuccess: Component //renderSuccess }) { // console.log("renderSuccess", renderSuccess); const { data, error, loading } = useFetch(url); if (loading) { return loadingFallback; } if (error) { return errorFallback; } if (data) { // return renderSuccess({ data }); return <Component data={data} />; } return null; } export default Fetch;