Let's understand JSX.Element vs React.ReactElement vs React.ReactNode step by step:
JSX.Element and React.ReactElement
JSX.Element and React.ReactElement are functionally the same type. They can be used interchangeably.
Consider below example:
const element = <div className="greeting">Hello, world!</div>;
When the above JSX code runs, it doesn't directly create something you can see on the screen. Instead, it creates a JavaScript object that describes that piece of UI. This object is like a blueprint or a recipe. This is how this blueprint or recipe object will look like:
const element = {
type: 'div',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
- type: This tells React what type of element we want to create. In this case, it's a
div.
- props: This is an object that holds all the properties (or "props") that we've passed to our element. Here, we've passed a
className prop with the value 'greeting'.
- children: This is a special prop that represents the content inside our element. In this case, it's the string
'Hello, world!'.
This object is what React uses to understand how to build and update the actual UI on the screen. When React sees this object, it knows to create a div element, give it a class of 'greeting', and put the text 'Hello, world!' inside it.
In a nutshell, we say A ReactElement is an object with a type and props.
So what is the difference between JSX.Element and React.ReactElement?
JSX.Element is a TypeScript type for JSX expressions, and React.ReactElement is a React type for React elements.
Is this correct?
const Component = ({
children,
}: {
children: JSX.Element;
}) => {
return <div>{children}</div>;
};
// Usage
<Component>hello world</Component>
In above stated example, TypeScript isn't happy because we declared the type of children to be JSX.Element, however, we are passing a string ("hello world") which is not a JSX.Element. Hence, we need a different type for children that can accept string, number, null, ReactElement ....
This is where React.ReactNode shines.
React.ReactNode
As per below definition of React.ReactNode.
React.ReactNode is a ReactElement, string, number, ReactFragment, ReactPortal, boolean, null & undefined.
declare namespace React {
type ReactNode =
| ReactElement
| string
| number
| ReactFragment
| ReactPortal
| boolean
| null
| undefined;
}
Example:
const Component = ({
children,
}: {
children: React.ReactNode
}) => {
return <div>{children}</div>;
};
// Usage
<Component> Hello World </Component>
Now TypeScript is happy!!
Happy coding!
class Example extends Component<ExampleProps> {for classes, andconst Example: FunctionComponent<ExampleProps> = (props) => {for function components (whereExamplePropsis an interface for the expected props). And then these types have enough information that the return type can be inferred.