> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/preactjs/preact/llms.txt
> Use this file to discover all available pages before exploring further.

# JSX

> Learn how to use JSX syntax with Preact and configure your build tools

JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside JavaScript files. Preact supports JSX and provides a lightweight implementation.

## What is JSX?

JSX allows you to write UI components using familiar HTML syntax:

```jsx theme={null}
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}
```

This is more readable than the equivalent JavaScript:

```javascript theme={null}
function Greeting({ name }) {
  return createElement('h1', null, 'Hello, ', name, '!');
}
```

## How JSX works

JSX is not valid JavaScript. It must be transformed by a compiler (like Babel or TypeScript) into function calls.

### The createElement function

Preact's `createElement()` function (aliased as `h()`) converts JSX into VNodes (`src/create-element.js:16`):

```javascript theme={null}
export function createElement(type, props, children) {
  let normalizedProps = {},
    key,
    ref,
    i;
  for (i in props) {
    if (i == 'key') key = props[i];
    else if (i == 'ref' && typeof type != 'function') ref = props[i];
    else normalizedProps[i] = props[i];
  }

  if (arguments.length > 2) {
    normalizedProps.children =
      arguments.length > 3 ? slice.call(arguments, 2) : children;
  }

  return createVNode(type, normalizedProps, key, ref, NULL);
}
```

### JSX transformation

This JSX:

```jsx theme={null}
<div className="container">
  <h1>Hello</h1>
  <p>Welcome to Preact</p>
</div>
```

Gets transformed to:

```javascript theme={null}
import { h } from 'preact';

h('div', { className: 'container' },
  h('h1', null, 'Hello'),
  h('p', null, 'Welcome to Preact')
);
```

<Note>
  The `h` function is Preact's alias for `createElement`, inspired by hyperscript conventions.
</Note>

## Configuring JSX

You need to configure your build tool to transform JSX and specify Preact as the JSX factory.

### Babel configuration

Add the React JSX transform plugin to your `.babelrc` or `babel.config.js`:

<CodeGroup>
  ```json .babelrc theme={null}
  {
    "plugins": [
      ["@babel/plugin-transform-react-jsx", {
        "pragma": "h",
        "pragmaFrag": "Fragment"
      }]
    ]
  }
  ```

  ```javascript babel.config.js theme={null}
  module.exports = {
    presets: [
      ['@babel/preset-env', {
        loose: true,
        targets: {
          browsers: [
            'chrome >= 40',
            'safari >= 9',
            'firefox >= 36',
            'edge >= 12'
          ]
        }
      }]
    ],
    plugins: [
      '@babel/plugin-transform-react-jsx'
    ]
  };
  ```
</CodeGroup>

With this configuration, you need to import `h` in every file that uses JSX:

```jsx theme={null}
import { h } from 'preact';

function App() {
  return <div>Hello</div>;
}
```

### TypeScript configuration

Configure TypeScript in your `tsconfig.json`:

```json tsconfig.json theme={null}
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",
    "target": "es2018",
    "module": "es2015",
    "moduleResolution": "node",
    "paths": {
      "preact": ["node_modules/preact/src/index.js"]
    }
  }
}
```

<Info>
  TypeScript requires you to import `h` even if you don't use it directly, as it's referenced in the transpiled output.
</Info>

### Automatic JSX runtime

Modern build tools support the automatic JSX runtime, which eliminates the need to import `h`:

<Tabs>
  <Tab title="Babel">
    ```json .babelrc theme={null}
    {
      "plugins": [
        ["@babel/plugin-transform-react-jsx", {
          "runtime": "automatic",
          "importSource": "preact"
        }]
      ]
    }
    ```
  </Tab>

  <Tab title="TypeScript">
    ```json tsconfig.json theme={null}
    {
      "compilerOptions": {
        "jsx": "react-jsx",
        "jsxImportSource": "preact"
      }
    }
    ```
  </Tab>

  <Tab title="esbuild">
    ```javascript theme={null}
    require('esbuild').build({
      jsx: 'automatic',
      jsxImportSource: 'preact',
      // ... other options
    });
    ```
  </Tab>
</Tabs>

With automatic runtime, you can write JSX without any imports:

```jsx theme={null}
// No imports needed!
function App() {
  return <div>Hello</div>;
}
```

## JSX expressions

You can embed any JavaScript expression in JSX using curly braces:

```jsx theme={null}
function UserInfo({ user }) {
  return (
    <div>
      <h1>{user.name}</h1>
      <p>Age: {user.age}</p>
      <p>Email: {user.email.toLowerCase()}</p>
      <p>Member since: {new Date(user.joined).getFullYear()}</p>
    </div>
  );
}
```

### Conditional rendering

<CodeGroup>
  ```jsx Ternary operator theme={null}
  function Status({ isOnline }) {
    return (
      <div>
        {isOnline ? <span>Online</span> : <span>Offline</span>}
      </div>
    );
  }
  ```

  ```jsx Logical AND theme={null}
  function Notifications({ count }) {
    return (
      <div>
        {count > 0 && <span>You have {count} notifications</span>}
      </div>
    );
  }
  ```

  ```jsx Null for nothing theme={null}
  function AdminPanel({ isAdmin }) {
    return (
      <div>
        {isAdmin ? <AdminTools /> : null}
      </div>
    );
  }
  ```
</CodeGroup>

## JSX attributes

JSX attributes use camelCase naming, except for `data-*` and `aria-*` attributes:

```jsx theme={null}
function Example() {
  return (
    <div
      className="container"
      onClick={handleClick}
      data-id="123"
      aria-label="Example"
      style={{ color: 'red', fontSize: '16px' }}
    >
      Content
    </div>
  );
}
```

<Warning>
  Use `className` instead of `class`, as `class` is a reserved keyword in JavaScript.
</Warning>

### Special attributes

Preact handles several attributes specially:

* `className` - Sets the element's CSS class
* `style` - Accepts an object of CSS properties
* `dangerouslySetInnerHTML` - Sets raw HTML (use with caution)
* `key` - Helps Preact identify elements in lists
* `ref` - Gets a reference to the DOM node

## Children

Everything between an opening and closing tag becomes the `children` prop:

```jsx theme={null}
function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

// Usage
<Card>
  <h2>Title</h2>
  <p>Content here</p>
</Card>
```

Children can be:

* Strings and numbers
* JSX elements
* Arrays of elements
* Functions (render props)
* `null`, `undefined`, or `false` (renders nothing)

## Fragments

Fragments let you group multiple elements without adding extra DOM nodes (`src/create-element.js:77`):

```javascript theme={null}
export function Fragment(props) {
  return props.children;
}
```

### Using fragments

<Tabs>
  <Tab title="Fragment component">
    ```jsx theme={null}
    import { Fragment } from 'preact';

    function List() {
      return (
        <Fragment>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
        </Fragment>
      );
    }
    ```
  </Tab>

  <Tab title="Short syntax">
    ```jsx theme={null}
    function List() {
      return (
        <>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
        </>
      );
    }
    ```
  </Tab>
</Tabs>

<Note>
  The `<>` short syntax requires configuring your build tool to recognize it as a Fragment.
</Note>

## Lists and keys

When rendering lists, each element should have a unique `key` prop:

```jsx theme={null}
function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.text}
        </li>
      ))}
    </ul>
  );
}
```

Keys help Preact identify which items have changed:

<CodeGroup>
  ```jsx Good - Unique IDs theme={null}
  todos.map(todo => (
    <li key={todo.id}>{todo.text}</li>
  ))
  ```

  ```jsx Bad - Array indices theme={null}
  todos.map((todo, index) => (
    <li key={index}>{todo.text}</li>
  ))
  ```
</CodeGroup>

## Real-world example

Here's a complete example from Preact's demo (`demo/index.jsx:68`):

```jsx theme={null}
import { Component, Fragment } from 'preact';
import { Router, Link } from 'preact-router';

class App extends Component {
  render({ url }) {
    return (
      <div class="app">
        <header>
          <nav>
            <Link href="/" activeClassName="active">
              Home
            </Link>
            <Link href="/todo" activeClassName="active">
              ToDo
            </Link>
            <Link href="/context" activeClassName="active">
              Context
            </Link>
          </nav>
        </header>
        <main>
          <Router url={url}>
            <Home path="/" />
            <Todo path="/todo" />
            <Context path="/context" />
          </Router>
        </main>
      </div>
    );
  }
}
```

This example demonstrates:

* Class component with JSX
* Props destructuring in render
* Nested JSX elements
* Component composition
* Conditional rendering via Router

## JSX gotchas

### Self-closing tags

Always close tags, even for elements that don't have children:

<CodeGroup>
  ```jsx Correct theme={null}
  <input />
  <br />
  <img src="photo.jpg" />
  ```

  ```jsx Wrong theme={null}
  <input>
  <br>
  <img src="photo.jpg">
  ```
</CodeGroup>

### JavaScript reserved words

Some HTML attributes conflict with JavaScript keywords:

* Use `className` instead of `class`
* Use `htmlFor` instead of `for`

### Comments

Use JavaScript comments inside JSX expressions:

```jsx theme={null}
function Example() {
  return (
    <div>
      {/* This is a comment */}
      <p>Content</p>
    </div>
  );
}
```
