---
title: Rendering | Components
contributors:
  - saisrikardumpeti
  - RATIU5
  - manucorporat
  - forresst
  - adamdbradley
  - zanettin
  - cunzaizhuyi
  - Pika-Pool
  - Kesmek
  - Craiqser
  - AnthonyPAlicea
  - mhevery
  - igorbabko
  - mrhoodz
  - thejackshelton
  - Balastrong
  - aendel
  - Jemsco
updated_at: '2023-09-19T17:37:26Z'
created_at: '2023-03-20T23:45:13Z'
---

import { Note } from '~/components/note/note';

# Rendering

Rendering is the process of updating the DOM based on changes in the state of the application and the component templates.

Qwik is unique because it knows how to render templates out-of-order asynchronously and in a fine-grained manner.


## JSX

Just like React, Qwik uses [JSX](https://facebook.github.io/jsx/) to express the component's template. Notice that JSX is only syntax, under the hood, React and Qwik are completely different. **JSX != VDOM**.

Qwik presents a few differences from other JSX frameworks:

- Components are always declared with the `component$` function.
- Components can use the `useSignal` hook to create reactive state.
- Event handlers are declared with the `$` suffix.
- For `<input>`, the `onChange` event is called `onInput$` in Qwik.
- HTML attributes are preferred. `class` instead of `className`. `for` instead of `htmlFor`.

```tsx /component$/#a /onClick$/#b /class/#c
import { component$, useSignal } from '@qwik.dev/core';

export const MyComponent = component$((props) => {
  const count = useSignal(0);
  return (
    <>
      <button
        onClick$={() => {
          count.value = count.value + props.step;
        }}
      >
        Increment by {props.step}
      </button>
      <main
        class={{
          even: count.value % 2 === 0, // conditional class
          odd: count.value % 2 === 1,
        }}
      >
        <h1>Count: {count.value}</h1>
      </main>
    </>
  );
});
```


## Rendering Child Components

Qwik lazy loads components on an as-needed basis. To minimize the number of components to download, Qwik only descends into child components if the component's props have changed.

```tsx {9} /Child/#a
import { component$, useSignal } from '@qwik.dev/core';

export const Parent = component$(() => {
  const count = useSignal(0);

  return (
    <>
      <button onClick$={() => (count.value += 1)}>Increment</button>
      <Child name={'World_' + count.value} />
    </>
  );
});

export const Child = component$((props: { name: string }) => {
  return <p>Hello {props.name}</p>;
});
```

<Note>In the above example, the Parent component passes a changing `name` property to the Child component. The Child component will only re-render when the count signal changes.</Note>

### Rendering a list of items

Qwik supports rendering lists with either `items.map()` or the experimental [`Each`](/docs/labs/each/) component.

For keyed collections, prefer [`Each`](/docs/labs/each/) once you have enabled it with `experimental: ['each']`. If you render with `items.map()`, every item in the list must have a unique `key` property on the first child returned by the mapping function. The `key` must be a string or number and must be unique within the list.

```tsx {6} /data.map/ /key/#a
import { component$ } from '@qwik.dev/core';

export const Parent = component$(() => {
  return (
    <>
      {data.map(({ message, uniqueKey }) => (
        <div key={uniqueKey}>
          <p>{message}</p>
        </div>
      ))}
    </>
  );
});
```

<Note>It is not recommended to use the array's index as the key unless you can guarantee that the data for a given key will always be the same. It is always preferred to use some unique identifier from the data as the key.</Note>

### Rendering Conditionally

Conditional rendering is done with the Javascipt [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) `?`, the `&&` operator, or just by using `if` statements.

Qwik also provides the experimental [`Show`](/docs/labs/show/) component for QRL-based
conditional control flow once it is enabled with `experimental: ['show']`.

```tsx
import { component$ } from '@qwik.dev/core';

export default component$(() => {
  const show = useSignal(false);
  return (
    <>
      <button onClick$={() => show.value = !show.value}>Toggle</button>
      {show.value ? <h1>Visible</h1> : <h1>Hidden</h1>}
      {show.value && <div>Only show when it's visible</div>}
    </>
  );
});
```

### `dangerouslySetInnerHTML`

Qwik offers an attribute on HTML Elements called `dangerouslySetInnerHTML` as a replacement for calling `innerHTML` on the DOM.

Due to cross-site-scripting (XSS) possibilities when rendering untrustworthy content, you must use `dangerouslySetInnerHTML` as a reminder that this operation might be dangerous.

```tsx
const htmlString = "<strong>hello</strong>";
<div dangerouslySetInnerHTML={htmlString}></div>
```

### `bind` Attribute

The `bind` attribute is a convenient API for two-way data binding of an `<input>` value to a `Signal`.

For checkbox inputs, you can use `bind:checked`, which binds the `checked` boolean to the specified signal.

```tsx /bind:value/ /bind:checked/ /firstName/#a /acceptConditions/#b
import { component$, useSignal } from '@qwik.dev/core';

export default component$(() => {
  const firstName = useSignal('');
  const acceptConditions = useSignal(false);

  return (
    <form>
      <input type="text" bind:value={firstName} />
      <input type="checkbox" bind:checked={acceptConditions} />

      <div>First name: {firstName.value}</div>
    </form>
  );
})
```

<Note>The API does not work with `useStore` since it does not return a signal. You can still use the manual approach, combining value and onInput$ as shown below.</Note>

The `bind:` is compiled away by the Qwik optimizer to a property set and an event handler, ie, it is just syntax sugar.

```tsx /bind:value/ /bind:checked/ /firstName/#a /acceptConditions/#b
import { component$, useSignal } from '@qwik.dev/core';

export default component$(() => {
  const count = useSignal(0);
  const firstName = useSignal('');
  const acceptConditions = useSignal(false);

  return (
    <form>
      {/* For number inputs, use `valueAsNumber` instead of `value` to get the numeric value directly */}
      <input type="number"
        value={count.value}
        onInput$={(_, el) => count.value = el.valueAsNumber }
      />
      <input type="text"
        value={firstName.value}
        onInput$={(_, el) => firstName.value = el.value }
      />
      <input type="checkbox"
        checked={acceptConditions.value}
        onChange$={(_, el) => acceptConditions.value = el.checked }
      />
      <div>First name: {firstName.value}</div>
    </form>
  );
})
```

<Note>This API ensures that the `value` of the input is always in sync with the value of the signal, no matter where the change comes from.</Note>


## Async Rendering

It is important for the rendering pipeline to be able to lazy load child components. Since lazy loading is an asynchronous operation, rendering must also be asynchronous. In practice, this means that the `render()` function must return a promise.

Most current-generation frameworks have a synchronous `render()` process. Synchronous rendering can't easily deal with asynchronous code loading, so synchronous rendering necessitates that all dependant components are eagerly present before rendering can commence.

## Render Batching

Whenever the state of the application changes, Qwik will schedule a render operation. The render operation will be scheduled to run after a macro-task (e.g. `setTimeout(0)`). This allows the application to batch multiple state changes into a single render operation.

In addition, because of the asynchronous nature of Qwik, all DOM writes are buffered and only flushed once all of the components have been downloaded and their JSX functions executed. The result is that the UI will update as an atomic operation, and the user will not see the intermediate steps, even if the application is slow to render.

The end goal is to enable performance and consistent rendering, even in the context of fast changing state and slow network.

## Rendering Work That Waits

Sometimes part of the UI needs to wait before it can show content, such as showing a fallback while a profile card, search result, or other section is still being prepared.

Wrap that part of the UI in [`<Suspense>`](/docs/labs/suspense/) when you want a fallback boundary:

```tsx /Suspense/
import { component$, Suspense } from '@qwik.dev/core';

export default component$(() => {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <UserCard />
    </Suspense>
  );
});
```

`<Suspense>` does not define the work. It only controls what renders while that part of the UI waits.

## Fine-grained Reactivity

Thanks to the fine-grained reactivity of Qwik, only the components that depend on the state will be updated. This is a big performance gain for two reasons:

1. Less code to execute means application updates will render faster.
2. Less code to execute means oftentimes the code does not have to be downloaded on application startup (or ever).
