Why React Component Names Must Begin With A Capital Letter?

Urvashi
5 min readFeb 2, 2024

--

One of the first things you learn about in React is components.

And very early on, you learn that:

React component names must always begin with a capital letter.

But have you ever wondered why?

How JSX Works

Well, the (long) answer to this question really lies in understanding how JSX works.

Here are two React components that return some simple JSX:

function Header() {
return <h1>Hello World</h1>
}

function App() {
return <Header />;
}

If you’ve been working with React for some time now, it’s natural to begin feeling that JSX is a part of React.

But JSX and React are two different things. You can actually use React without JSX and you can use JSX outside of React.

JSX stands for JavaScript XML and it is usually referred to as a syntax extension for JavaScript. It allows you to write HTML-like code within your JavaScript files, making it easier to create and manage the UI components.

But JSX is neither standard JavaScript nor standard HTML.

Just like how you can’t run TypeScript directly inside the browser, similarly, you can’t run JSX directly within the browser.

const element = <h1>Hello World</h1>
Error after running JSX

Similarly, React.js which is a JavaScript library, does not understand JSX as it is.

So you need to first convert this JSX into regular JavaScript. This is usually done for you automatically during the build process.

If you’re using Create-React-App, then Webpack (Babel) does this for you.

If you’re using Vite, esbuild does this for you.

If you’re Next.js, then the Speedy Web Compiler (SWC) does this for you.

You can try out SWC online to see how the transformed JSX looks like:

// Input
const element = <h1>Hello World</h1>
// Output
var element = React.createElement("h1", null, "Hello World");

In the above code, notice how JSX is transformed into React.createElement function calls.

Similarly, you can try out Babel online:

// Input
const element = <h1>Hello World</h1>
// Output
import { jsx as _jsx } from "react/jsx-runtime";
const element = /*#__PURE__*/_jsx("h1", {
children: "Hello World"
});

The compiled code in Babel looks slightly different. Instead of the React.createElement function, there’s a _jsx function.

This _jsx function (new JSX transform) is available in Babel v7.9.0 and above. It’s just an extra layer that between JSX and the React.createElement() calls.

You can learn about it here.

Remember the times when you had to always import React? The new JSX transform gets rid of the requirement to have a React identifier in scope (even if you were not using it directly).

Let’s talk about the final React.createElement() function calls. These function calls are just regular JavaScript functions that return plain JavaScript object representing parts of the UI.

These objects are called “React elements”. React uses these objects to construct the DOM and keep it up to date. But we won’t go into details about that here.

const element = React.createElement("h1", null, "Hello World")
console.log(element)
React Element

Answering why React component names must begin with a capital letter

Well this is to differentiate your custom components from in-built HTML elements.

Notice the first argument that’s passed to the React.createElement() calls:

createElement(type, props, ...children)

type: The type argument must be a valid React component type. For example, it could be a tag name string (such as 'div' or 'span'), or a React component (a function, a class, or a special component like Fragment).

When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <h1> and results in a string 'div' or 'h1' passed to React.createElement.

// Input
function Header() {
return <h1>Hello World</h1>
}
// Output
function Header() {
return React.createElement("h1", null, "Hello World");
}

Types that start with a capital letter correspond to a component defined or imported in your JavaScript file.

// Input
function App() {
return <Header />;
}
// Output
function App() {
return React.createElement(Header, null);
}

If you don’t start your component name with a capital letter, then React will render a corresponding HTML tag instead. This remains the same for component names that don’t correspond to valid HTML element names.

// Input 
function heading() {
return <h1>Hello World</h1>
}
function App() {
return <heading />;
}
// Output
function heading() {
return React.createElement("h1", null, "Hello World");
}
function App() {
return React.createElement("heading", null);
}
Expected HTML:
<h1>Hello World</h1>

Rendered HTML in browser:
<heading></heading>

That’s why you must start your component names with a capital letter.

If you do have a component that starts with a lowercase letter, assign it to a capitalised variable before using it in JSX like this:

function heading() {
return <h1>Hello World</h1>
}

function App() {
const Heading = heading
return <Heading />;
}

Though this approach is not recommended and will only result in confusion.

Using React without JSX

Since JSX is just syntactic sugar for calling React.createElement(component, props, ...children), therefore you can directly create elements using this function but it might not be as convenient as JSX.

import { createElement } from 'react';

function Greeting({ name }) {
return createElement(
'h1',
{ className: 'greeting' },
'Hello'
);
}

Using JSX without React

JSX, while most commonly associated with React, can also be used in other libraries and frameworks like:

1. Preact: A lightweight alternative to React, Preact supports JSX out of the box.
2. Inferno: Another React-like library that is optimized for performance, it can utilize JSX.
3. Vue.js: With certain configurations, Vue can use JSX for rendering components.

--

--