Skip to content

Fundamentals of React functional components you should know

In this blog I would like to demystify React’s functional components. I want to give you a deeper understanding of why React works as it does, so that you can focus on writing React applications instead of hunting bugs.

Function components – the mental model gap

In the “Main Concepts” section in the React docs they tell you what a function component is with a simple example.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

In the React docs, Main Concepts in the section Function and Class Components they say:

This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “function components” because they are literally JavaScript functions.

React docs – Main Comcepts – Function and Class Components

With this statement they build a mental model of React that has a gap. The function you see above is not a component, it is simply a function. I should better say: “is not a component yet”. It will become a component when you use it in JSX, e.g. <Welcome/>. But then it is more then a function, because it will get state. You should keep this in mind to prevent yourself from making mistakes as we will see when it comes to React Hooks.

So what will happen if you invoke the Example function directly.

const example = Example()

You will then get the error:

Unhandled Rejection (Error): Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

The statement “can only be called inside of the body of a function component” makes clear that the Example function is not the functional component. Otherwise the error would not make sense.

So what makes Example a functional component? A functional component is something that is connected to React. You usually make it a funtional component by using it in JSX.

<Example/>

You can see the difference when you take a look at the transformed code that the JSX transformer produces. You will see something like this:

React.createElement(Example, {}, null)

As you can see the Example function becomes a component when it is wrapped by React.createElement what it makes it a ReactElement. And this makes the big difference, because the ReactElement connects the simple Example function to React. It is this wrapper that restores the component’s state before calling the Example function so that all the hooks like useState, useMemo, useCallback, etc. will work. Otherwise the Example function is not connected and therefore the component’s state is not available what will lead to the error I showed above.

Understanding React Hooks

The effects of the mental model gap can be severe when it comes to the component state and the mental model gap will grow. React hooks can only be understood if you are aware of the ReactElement wrapper and how it augments your function to make it a real functional component. So let’s take a look at a hooks example from the React docs – Introducing Hooks.

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

The example looks nice and condensed, but even more questions arise and the mental model gap grows:

  • Example calls the function useState and useState returns the state.
    But since useState is just a function how can it remember the previous value – it’s state?
  • There might be multiple functional components that all call the same useState function.
    How is the state separated between different components?

You can only answer these questions if you know how the wrapper function that React.createElement creates works.

Whenever the ReactElement is called it restores the components state before it calls the function that implmenets the component.

Also take a look at my stackoverflow answers related to functional components:

Leave a Reply

Your email address will not be published. Required fields are marked *

 

GDPR Cookie Consent with Real Cookie Banner