React elements, JSX, and React components

Publication date
April 25th, 2025

React elements

This is a React element.

{
  $$typeof: Symbol(react.transitional.element),
  type: 'div',
  props: {
    children: 'Hello, world.'
  }
}

It's an object that describes a HTML element, which, in this case, is a <div> with the text content Hello, world. inside. You can create one of these with this code:

import { jsx } from 'react/jsx-runtime';

jsx('div', { children: 'Hello, world.' });

JSX

But for large, nested React elements, it looks much nicer to use the "JSX" syntax, as it looks more like the HTML we are describing:

<div>Hello, world.</div>

JSX isn't valid JavaScript, so in order to run this code, we have to first transform it with a "JSX transform" to convert it back to the jsx() function call. Most tools within which you create a React app will do this for you via a build step.

React components

A React "component" is a function that returns a React element:

function SayHello(props: { name: string }) {
  return <div>Hello, {props.name}.</div>;
}

Calling this function will return the same React element for the <div> we saw above:

SayHello({ name: 'world' });

as, when run through the JSX transform, this final code looks something like this:

function SayHello(props: { name: string }) {
  return jsx('div', { children: `Hello, ${props.name}.` });
}

React components in JSX

But you can also use this function in JSX syntax as if it were an HTML element:

<SayHello name="world" />

and if you do, does it evaluate to that same <div> React element? Actually, no! It evaluates to this:

{
  $$typeof: Symbol(react.transitional.element),
  type: SayHello,
  props: { name: 'world' }
}

This is also a React element! But instead of describing an HTML element, it describes our SayHello function as if it were an HTML element. Instead of having a string type that corresponds to an HTML tag name, the type of this element is the React component function itself that was used in the JSX. The "props" of the <div> React element are the HTML attributes that a div supports, whereas the props of the SayHello React element is the object passed in as the first parameter to SayHello when it's called.

Just as the original <div> React element describes an HTML element, this React element describes the intention to call the SayHello function and use the HTML React element that it evaluates to. The function hasn't actually been called yet. Again, all we've done by writing <SayHello name="world" /> is declare, via a React element, that we want to call the SayHello function, pass in { name: 'world' } as its props, and use whatever React element it yields. It's very important to understand the distinction between SayHello({ name: 'world' }) and <SayHello name="world" /> in that the first executes a function and returns a React element, while the second describes the intention to execute the function.

Why does this matter?

When this component function is eventually executed, that execution that yields a React element is called "rendering." At the risk of stating the obvious, in order to "render" a React component, the code inside that function needs to be able to execute to completion. As that code could rely on any number of variables defined in a parent/ancestor scope, where a component is "rendered" matters, because it influences what code can or cannot be run, depending on whether it's run in the browser or on a server. More on that next time...