Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

235
Views
React: Ways of passing component as a props

What is difference between these two way of passing component as props.

  1. Passing RepoMenu as it is:
<Fetch
  url={`https://api.github.com/users/${login}/repos`}
  renderSuccess={RepoMenu}
/>
  1. Wrapping the RepoMenu in 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}>&lt;</button>
      <p>{name}</p>
      <button onClick={next}>&gt;</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

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

return renderSuccess({ data });

Your problem is you're calling a component like a function. Every time you call renderSuccess (which is RepoMenu - now it's not considered a component), it will trigger your custom hook useIterator which is invalid.

You can refer to this document

Don’t call Hooks inside loops, conditions, or nested functions.

Nested functions part is your current situation.

With the pure component, it was working because you didn't use any hooks, that's why you don't see any errors come out.

For the fix, you can do it this way

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;

Sandbox

about 4 years ago · Juan Pablo Isaza Report

0

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;
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!