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

342
Views
React hooks: call component as function vs render as element

Say we have component:

let Component = (props)=><div>Hi</div>;

I have sometimes come across code where someone calls a react component as function in render:

 const App = () => (
     <div> {Component()} </div>
 )

vs rendering it as element

 const App = () => (
     <div> <Component/> </div>
 )

In react hooks, what are possible drawbacks of calling component as function?


There is similar question but it is not specifically targeted at hooks - also that question is more about performance.

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Here are some implications of calling component as function vs rendering it as element.

  1. Potential violation of rules of hooks

When you call a component as a function (see TestB() below) and it contains usage of hooks inside it, in that case react thinks the hooks within that function belongs to the parent component. Now if you conditionally render that component (TestB()) you will violate one of the rules of hooks. Check the example below, click the re-render button to see the error:

Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

 
function TestB() {
  let [B, setB] = React.useState(0);
  return (
    <div
      onClick={() => {
        setB(B + 1);
      }}
    >
      counter B {B}
    </div>
  );
}
 

function App() {
  let [A, setA] = React.useState(0);

  return (
    <div>
      <button
        onClick={() => {
          setA(A + 1);
        }}
      >
        re-render
      </button>
      {/* Conditionally render TestB() */}
      {A % 2 == 0 ? TestB() : null}
    </div>
  );
}
ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Now you can use <TestB/> instead and see the difference.

  1. Reconciliation might not work as expected

When you render a react component as react element say <TestB/> and then on next render you render some different component <TestC/> instead of it (in the same place in component hierarchy), due to reconciliation algorithm (and since component type has changed), react will unmount <TestB/> component (all its state will be gone) and mount a new component <TestC/> instead.

If you call it as function however (e.g. TestB()), the component type will not participate in reconciliation anymore and you might not get expected results:

function TestB() {    
  return (
    <div     
    >
      <input/>
    </div>
  );
}
function TestC() {
  console.log("TestC")
  return (
    <div     
    >
      <input/>
    </div>
  );
}

function App() {
  let [A, setA] = React.useState(0);

  return (
    <div>
      <button
        onClick={() => {
          setA(A + 1);
        }}
      >
        re-render
      </button>
      {/*  Here we are alternating rendering of components */}
      {A % 2 == 0 ? TestB() : TestC()} 
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

  • Type something in the input
  • Now click the re-render button
  • You can see now from the log that component TestC was rendered, but the input shows the same value you typed before - which might not be what you want as you rendered a different component. This happened because reacts reconciliation algorithm couldn't detect that we moved to a different component (from TestB to TestC) and didn't remove previous input instance from DOM.

Render these components as elements now (<TestB/> and <TestC/>) to see the difference.

over 4 years ago · Santiago Trujillo 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!