Trust is earned, not given

A different perspective

2026-09-15 · Projects

React.js, part 20: where React is heading — the Activity component and rendering what is offscreen

Part 20from the React.js series · 20 parts in all

The last thread to pull is the one that ties the concurrent work together: React is learning to keep a tree mounted while hiding it, instead of destroying and rebuilding it. The Activity component is the clearest expression of that idea — and the natural place to end a series that began with an interruptible renderer.

Activity: hidden, not unmounted

Switching tabs, collapsing a panel, navigating within a wizard — today those unmount the inactive tree, throwing away scroll position, form entries, pending state, and DOM. Wrapping the tree in <Activity mode="hidden"> instead keeps it mounted but visually hidden and deprioritized:

<Activity mode={tab === 'draft' ? 'visible' : 'hidden'}>
  <DraftEditor />
</Activity>
<Activity mode={tab === 'preview' ? 'visible' : 'hidden'}>
  <PreviewPane />
</Activity>

Switching tabs becomes a visibility change: no state loss, no re-fetch, and instant switching because the tree already exists. Effects are paused while hidden and resumed on return, which is the part that requires care — an effect that assumed unmount as its only teardown point must still clean up on hide.

Offscreen rendering as a primitive

Underneath, hidden content can still be pre-rendered: React may render it at low priority so it is ready before the user ever shows it. That is the same machinery as transitions and Suspense, pointed at a different goal — instead of "show the old UI while the new one loads", it is "prepare the new UI before the user asks".

What this changes for the design of a component

The through-line of the whole series

React 18 gave the renderer the ability to interrupt and resume. Everything since has been about exposing that power in datatypes you can reason about: transitions for urgency, Suspense for pending, actions for form lifecycles, optimistic state for latency, the compiler for memoization, and now Activity for visibility. The unifying idea is that a component should describe what the UI is for a given state, and React should be free to decide when — and how much of it — to actually render. That is a much more interesting contract than the one this series started with, and it is why the ordinary props-and-state React you already know still composes cleanly with all of it.