DEV Community

Cover image for JSX Element, React Node, React Element
Muhammad Ridho Anshory
Muhammad Ridho Anshory

Posted on

1 1 1

JSX Element, React Node, React Element

I am currently migrating a React application to TypeScript. So far, this works pretty well, but I have a problem with the return types of my render functions, specifically in my functional components.

Cut a long story short, I have these questions during my learning process:

  1. What is the difference between JSX.ElementReactNode and ReactElement?
  2. Why do the render methods of class components return ReactNode, but functional components return ReactElement?

What is the difference between JSX.ElementReactNode and ReactElement?

A ReactElement is an object with a type and props.

type Key = string | number

 interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
    type: T;
    props: P;
    key: Key | null;
}
Enter fullscreen mode Exit fullscreen mode

A ReactNode is a ReactElement, a ReactFragment, a string, a number or an array of ReactNodes, or null, or undefined, or a boolean:

A ReactNode is a ReactElement, a ReactFragment, a string, a number or an array of ReactNodes, or null, or undefined, or a boolean:

type ReactText = string | number;
type ReactChild = ReactElement | ReactText;

interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
Enter fullscreen mode Exit fullscreen mode

JSX.Element is a ReactElement, with the generic type for props and type being any. It exists, as various libraries can implement JSX in their own way, therefore JSX is a global namespace that then gets set by the library, React sets it like this:

declare global {
  namespace JSX {
    interface Element extends React.ReactElement<any, any> { }
  }
}
Enter fullscreen mode Exit fullscreen mode

By example:

<p> // <- ReactElement = JSX.Element
   <Custom> // <- ReactElement = JSX.Element
     {true && "test"} // <- ReactNode
  </Custom>
 </p>
Enter fullscreen mode Exit fullscreen mode

Why do the render methods of class components return ReactNode, but functional components return ReactElement?

they do return different things. Components return:

render(): ReactNode;
Enter fullscreen mode Exit fullscreen mode

tl;dr: It is a current TS type incompatibility not related to core React.

  • TS class component: returns ReactNode with render(), more permissive than React/JS
  • TS function component: returns JSX.Element | null, more restrictive than React/JS

In principle, render() in React/JS class components supports the same return types as a function component. With regard to TS, the different types are a type inconsistency still kept due to historical reasons and the need for backwards compatibility.

Ideally a valid return type would probably look more like this:

type ComponentReturnType = ReactElement | Array<ComponentReturnType> | string | number
  | boolean | null // Note: undefined is invalid
Enter fullscreen mode Exit fullscreen mode

If you guys have other thoughts leave a comment I'll update the post base on your solutions as well.. cheers🍻

💡 One last tip before you go

Tired of spending so much on your side projects? 😒

We have created a membership program that helps cap your costs so you can build and experiment for less. And we currently have early-bird pricing which makes it an even better value! 🐥

Just one of many great perks of being part of the network ❤️

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay