Choosing the right type: Unraveling the difference between JSX.Element and React.FC in React components

René Kulik on 28.01.2024

Introduction

I really like explicit return types as you see what will be the result of a function at the first glance. That is why, when I work with TypeScript, I enforce return types by using the "@typescript-eslint/explicit-function-return-type": "error" rule from @typescript-eslint/eslint-plugin in my ESLint configuration. With that ESLint complains when the return type is not explicitly set:

const foo = () => { // Missing return type on function.eslint@typescript-eslint/explicit-function-return-type
  return 'bar';
}

Defining general types is straight forward, but when it comes to React there are two potential types you can use for components, JSX.Element and React.FC. In this blogpost I am going to explain both types, talks about their pros and cons, and tell you which one I am using.

JSX.Element

JSX.Element defines a representation of a DOM element. In the following example the returned element is a div:

const Example = (): JSX.Element => {
  return <div>Hello, world!</div>;
}

Using JSX.Element as the type for React components works in most use-cases, but sometimes components should also be able return null or a simple string. As JSX.Element does represents those types there will be an error:

const Example = (): JSX.Element => {
  return null; // Type 'null' is not assignable to type 'Element'.
}

To make the code work the return type has to be extended:

const Example = (): JSX.Element | null => {
  return null;
}

React.FC

React.FC on the other hand defines a functional component that returns a JSX element. It is also a generic that can be used to specify component props:

const Example: React.FC<{ name: string }> = (props) => {
  return <div>Hello, {props.name}!</div>;
}

Compared to JSX.Element also null and string are represented:

const Example: React.FC = () => {
  return null;
}

In former React versions React.FC was avoided as it opened up components with an implicit children prop. Since React 18 this is not the case anymore.

Conclusion

In this blogpost I described JSX.ELement and React.FC as types for React components and outlined their pros and cons. Personally I use React.FC over JSX.Element because it does not limit the return type to DOM element representations. Furthermore its generic functionality can be used to define props.