Each

Each is a built-in Qwik component for rendering keyed lists.

It is most useful when list items have a stable identity and you want Qwik to preserve and move existing rows instead of re-rendering the whole list when the order changes.

import { Each, component$, useSignal } from '@qwik.dev/core';
 
type Todo = {
  id: string;
  label: string;
};
 
export default component$(() => {
  const todos = useSignal<Todo[]>([
    { id: '1', label: 'Write docs' },
    { id: '2', label: 'Review keys' },
    { id: '3', label: 'Ship it' },
  ]);
 
  return (
    <>
      <button onClick$={() => (todos.value = [...todos.value].reverse())}>
        Reverse order
      </button>
 
      <ul>
        <Each
          items={todos.value}
          key$={(todo) => todo.id}
          item$={(todo) => <li>{todo.label}</li>}
        />
      </ul>
    </>
  );
});

Props

Each accepts three props:

  • items: the array to render
  • key$: returns a stable unique key for each item
  • item$: returns the JSX for one item

item$ must return a single JSX node. If you need multiple siblings, wrap them in a container element or a Fragment.

import { Each, Fragment, component$ } from '@qwik.dev/core';
 
export default component$(() => {
  return (
    <ul>
      <Each
        items={['a', 'b', 'c']}
        key$={(item) => item}
        item$={(item) => (
          <Fragment>
            <li>Item {item}</li>
          </Fragment>
        )}
      />
    </ul>
  );
});

Each vs items.map()

If your list items have stable keys, prefer Each.

It is the specialized keyed-list primitive in Qwik and is designed to preserve and move existing rows efficiently.

Use items.map() for simple list rendering or when you do not have a stable key:

<ul>
  {todos.value.map((todo) => (
    <li key={todo.id}>{todo.label}</li>
  ))}
</ul>

Prefer Each when:

  • items have stable ids
  • rows are frequently reordered, inserted, or removed
  • you want to preserve existing row DOM and component instances

Prefer map() when:

  • there is no stable key for the item
  • you want ordinary JSX list rendering without Each's keyed-row preservation behavior
  • the row output should be recomputed from replaced item objects even when the key stays the same

How keyed updates work

Each uses the value from key$ as the identity of the row.

When keys stay the same, Qwik can move and reuse the existing rows instead of recreating them. This is why Each is a good fit for drag-and-drop lists, sortable tables, and other UIs where items move around often.

There is an important tradeoff: if you replace an item object but keep the same key, Each preserves the existing row. That means the row template is not re-run just because a new object with the same key was passed in.

So Each is usually the right choice for keyed collections. It has a different update strategy.

If you need the row output to update from replaced item objects, prefer map(). If you need row-local updates with Each, model that row state with Qwik reactivity instead of relying on replacing the whole item object.

Keys

Choose keys that are stable across renders:

  • Good: database ids, slugs, UUIDs
  • Avoid: array indexes when the list can be reordered

Using unstable keys defeats the main benefit of Each and can produce confusing UI behavior.