JSX in React TypeScript Explained Simply

React is a JS library that allows you to make web UI’s that is very similar to HTML. JSX is for more strict compared to HTML and it is dynamic.

You may be asking yourself, why use JSX when we have HTML?

In order to use JSX, you must do two things:

  1. Name your files with a .tsx extenstion
  2. Enable the jsx option

Underneath the hood, React is transforming JSX into Javascript

var Nav;
// Input (JSX):
var app = <Nav color="blue" />;
// Output (JS):
var app = React.createElement(Nav, {color:"blue"});

Different TypeScript JSX Modes

Typescript ships with three JSX modes: preserve, react, and react-native. These modes only affect the emit stage – aka type checking will be unaffected.

The preserve mode will keep JSX as part of the output to be further consumer by another transform step and output file will have .jsx extension.

The react mode will emit React.createElement, does not need to go through a JSX transformation before use.

The react-native mode is the equivalent of preserve in that it keeps all JSX.

The react-jsx mode helps you to avoid the necessity of importing React in every file.

Type Checking

In order to understand type checking with JSX, you must first understand the difference between intrinsic elements and value-based elements.

  • Intrinsic Elements – are emitted as strings and are typically plain old HTML elements represented in JSX form. Intrinsic elements don’t have props or attributes.
  • Value Based Elements – are typically components you created ex. <MyComponent />. Value based elements have props and can have there own values specified.

Value based components are typically what you think of with traditional React components and they must be captialized.

ReactNode vs JSX.Element vs React.ReactElement

When the TypeScript team started working on supporting React, JSX proved to be a huge stumbling block. Its syntax doesn’t exist in JavaScript, so they had to build it into the compiler.

JSX.Element

const Component = () => {
    return <div>Hello world</div>
};

JSX is similar to a global namespace and is globally scoped. Namespaces are essentially bundles of types and using JSX.Element will be picked up by TypeScript.

You should typically use JSX.Element for most cases and what React applies to JSX React elements by default.

React.ReactNode

This is where React.ReactNode comes in. It’s a type that accepts everything that React can render.

ReactNode is used as a return type for render() in class components and generally

declare namespace React {
  type ReactNode =
    | ReactElement
    | string
    | number
    | ReactFragment
    | ReactPortal
    | boolean
    | null
    | undefined;
}

React.ReactElement

Elements are the smallest building blocks of React apps.

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

ReactElement is an interface with three keys: type, props, and keys.

ReactElement is not as widely used but is useful for parsing children utilities (React.Children.forEach).

ReactElement can be useful for reading props, type, and key properties when parsing children with one of the React.Children properties,

Leave a Reply

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