Key each item to reorder

One keyed boundary per item lets a sort glide instead of jump.

React docsreact.dev
It's important to properly use keys to preserve identity when reordering lists.
Animating reorder of items in a listRead docs ↗

From vercel-react-view-transitions, SKILL.md.

Sort the same list

Change the sort a few times.

One for the whole listBad
<ViewTransition><List />
One per itemGood
<ViewTransition key={item.id}>
const [sort, setSort] = useState('newest');
const [optimisticSort, setOptimisticSort] = useOptimistic(sort);

function cycleSort() {
  const nextSort = getNextSort(optimisticSort);
  startTransition(() => {
    setOptimisticSort(nextSort); // label: before the snapshot, no animation
    setSort(nextSort);           // list: between snapshots, animates
  });
}

<button onClick={cycleSort}>Sort: {LABELS[optimisticSort]}</button>
{items.sort(comparators[sort]).map(item => (
  <ViewTransition key={item.id}><ItemCard item={item} /></ViewTransition>
))}

Why it matters, pros and cons

Why it matters

A boundary per item gives each row its own snapshot, so the browser can move it. One boundary around the list can only cross-fade the whole block.

Pros

  • Rows travel; the new order is legible.
  • Adds and removes get enter and exit.
  • Server sorting via router.replace works the same.

Cons

  • No wrapper div between map and the boundary.
  • default="none" on items stops the glide.
  • Optimistic order resolves before the snapshot; it won't animate.