React doesn't have the same execution order when calling a component as a function rather than using it as a tag?

Viewed 65

I was just doing some experimentation and I noticed if I have:

const Component1 = () => {
  console.log("Component1");
  return <div>Component1</div>;
};
const Component2 = () => {
  console.log("Component2");

  return <div>Component2</div>;
};

Now when using the components like this:

export default function App() {
  const [state, setState] = useState(false);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <Component1 />
      {Component2()}

      <button onClick={setState.bind(null, !state)}>Change State</button>
    </div>
  );
}

I noticed that in console.log component2 appears before component1 even tho they are rendered in the correct order, why does this happen?

2 Answers

JSX elements are syntax sugar for React.createElement. React.createElement does not run the components inside it immediately:

const TheComponent = () => {
  console.log('component being created');
};
React.createElement(TheComponent);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

Rather, it waits for the elements to be rendered.

When you do

<Component1 />
{Component2()}

You call Component2 immediately, but since the rendering doesn't occur instantaneously - it occurs a little bit of time later - Component1 takes a bit of time to log.

Note that you should never use

{Component2()}

when rendering an element - always use JSX syntax or React.createElement, as React expects you to do.

Related