React Components are Just Functions

December 16, 20203 min read

When developing React components it's easy to think of them as their own beast. It's important however to realize that they are just an abstraction over regular javascript functions.


What is React?

React components are the low level building blocks that make up a react application. So to understand what components are, let's first understand what react is.

React is a declarative, efficient, and flexible JavaScript library for building user interfaces. - React Docs

Here's a basic React component:

function Hero() {
return (
<div>
<h1>Hi, I'm Dillon!</h1>
<p>This is my react component</p>
</div>
)
}

Our markup in the middle is React's templating language called JSX. It's important to note that JSX is simply an abstraction that sits above the createElement method exported from React. This is what the above code looks like without utilizing the JSX abstraction:

return React.createElement('div', null,
React.createElement('h1', null, "Hi, I'm Dillon!"
React.createElement('ul', null, "This is my react component")
);

As you can see, the JSX in our Hero component is really just syntactic sugar for calling the createElement method exported by React. Let's take a closer look at createElement 's function signature.

React.createElement(component, props, ...children)

Now let's break down each of the arguments this nifty function named createElement accepts.


Component

React.createElement(component, props, ...children)

The first argument, component, takes a string representing any native HTML elements (ex. "div", "h1", "p" etc.). This is what we did in our Hero example. You can also pass plain old javascript functions as an argument for component. The fact that the createElement method can take in a javascript function is a key point here. More on that to come, first let's take a look at the 2nd argument, props.


Props

The second argument we pass to createElement is props. Props is just a plain javascript object. From the React Official Documentation:

When React sees an element representing a user-defined component, it passes JSX attributes and children to this component as a single object. We call this object “props”.

In our Hero example, we didn't include any attributes to our JSX elements, therefore props was null. We'll take a look a closer look at how props work in the next section.


Children

Children are the components nested inside of the JSX element. Let's look again at our example:

function Hero() {
return (
<div>
<h1>Hi, I'm Dillon!</h1>
<p>This is my react component</p>
</div>
)
}

The children of this JSX element "div" are the "h1" and the "p" elements. Those elements also have children. The "h1" element has 1 child, which is the string "Hi, I'm Dillon!". The "p" tag also has 1 child, which is the string "This is my react component." Now looking again at our transpiled version of this code:

return React.createElement(
'div',
null,
React.createElement('h1', null, "Hi, I'm Dillon!"),
React.createElement('ul', null, 'This is my react component')
)

We can see that JSX is just a series of nested calls to createElement. It's really 1 call to createElement with nested calls passed as the third argument (children). In this example we are passing 'div' as the first argument, which can either be a string value of the HTML element you want to create, or a function. Next, we pass null as the value for props since we aren't passing any props to these elements.


What are React components?

React components let you split the UI into independent, reusable pieces, and think about each piece in isolation.

Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.

Let's look again at our simple React component:

function Hero() {
return (
<div>
<h1>Hi, I'm Dillon!</h1>
<p>This is my react component</p>
</div>
)
}

This isn't too interesting in that it's a function that takes no inputs and spits out some markup. Let's take a closer look at how props work to understand how our component becomes dynamic.

function Hero(props) {
return (
<div>
<h1>Hi, I'm {props.name}!</h1>
<p>This is my react component</p>
</div>
)
}

In our h1 tag we are now accessing the property name on an object called props? Now how is this possible? What is props really and how do we have access to it here? This really has more to do with whoever is invoking Hero than Hero itself. Let's go one level up and see what happens when we invoke this component.


Let's say we are developing a marketing page. We have a Home page component and inside of it we want to render our Hero component. That would look something like this:

function Home() {
return <Hero name="Dillon" />
}

If we transpile the return value, we should now know what to expect, a call to createElement:

return React.createElement(Hero, { name: 'Dillon' })

This is cool. Now, we are passing a value to createElement's second argument, props.

When React sees an element representing a user-defined component, it passes JSX attributes and children to this component as a single object. We call this object “props”.

So when this createElement method is invoked by React, under the hood it is passing an object called props to our function Hero. That is why when we declare our component Hero , we can access the name value from the props object that React so conveniently made available to us.


Just functions

I hope I was able to show that we can use the word component and function interchangeably when talking about React. The createElement method takes a function as it's first argument, those are our custom "user-defined" components, like our Hero component. When React invokes that function, it passes along props as a single object. As we saw, JSX is just syntactic sugar for the createElement method:

function Home() {
return <Hero name="Dillon" />
}
return React.createElement(Hero, { name: 'Dillon' })

The two snippets above are just two ways of writing the same thing.


Resources

With this understanding of React components as just functions we can apply principles of writing quality functions to writing quality react components. Here are some resources for learning those principles:


Readable Functions Do one Thing

Functions - Eloquent Javascript

The art of writing plain and small functions