'React: Ways of passing component as a props
What is difference between these two way of passing component as props.
- Passing
RepoMenuas it is:
<Fetch
url={`https://api.github.com/users/${login}/repos`}
renderSuccess={RepoMenu}
/>
- Wrapping the
RepoMenuin a function
<Fetch
url={`https://api.github.com/users/${login}/repos`}
renderSuccess={({ data }) => <RepoMenu data={data} />}
/>
RepoMenu internally uses a custom hook.
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>
);
}
Using one (Passing RepoMenu as it is) starts failing, React starts throwing an exception Rendered more hooks than during the previous render.
Initially i thought may it is not possible to use the component like the method 1. But to test it more further i created a small Pure Component and just tried to render the data passed to it.
function RepoMenuPure({ data = [], onSelect = (f) => f }) {
return (
<div style={{ display: "flex" }}>
<h3>There are {data.length} repos for this user</h3>
</div>
);
}
And when i tried to use it like below, It worked in this case.
const UserRepositories = ({ login, selectedRepo, onSelect = (f) => f }) => {
return (
<Fetch
url={`https://api.github.com/users/${login}/repos`}
renderSuccess={RepoMenuPure}
/>
);
};
Can someone please help me explain what is happening and what i am missing?
I have created a small sandbox here: https://codesandbox.io/s/stackoverflow-example-bqfn3e?file=/src/App.js
Solution 1:[1]
In the first option :
renderSuccess={({ data }) => <RepoMenu data={data} />}
You are saying that Fetch component expects that renderSuccess receives a function that returns a Component. If you were using typescript, the type of renderSuccess in Fetch would be something like:
renderSuccess : (data: any) => JSX.Element
// OR return the component itself
renderSuccess : (data: any) => RepoMenu
And that´s why when you call renderSuccess({ data }) inside Fetch component works.
In the second option:
renderSuccess={RepoMenu}
You are saying that Fetch component expects that renderSuccess receives the RepoMenu Component (not a function). If you were using typescript, the type of renderSuccess in Fetch would be something like:
renderSuccess : JSX.Element
// OR the component itself
renderSuccess : RepoMenu
For this option work, you should change your Fetch component to something like this:
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;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Luis Paulo Pinto |
