Skip to main content
Rendering is the process of converting your components into actual DOM elements that appear in the browser.

The render function

Preact’s render() function mounts a component tree into a DOM element (src/render.js:12):

Basic usage

Import render and mount your app:
Rendering to document is automatically converted to document.documentElement to avoid issues.

Mounting to a container

It’s common to render into a dedicated container element:

Initial render vs updates

Preact handles initial renders and subsequent updates differently:

Initial render

On first render, Preact:
  1. Creates a VNode tree from your components
  2. Generates real DOM nodes
  3. Inserts them into the parent container
  4. Calls lifecycle methods like componentDidMount

Subsequent renders

When you call render() again on the same container:
  1. Preact finds the previous VNode tree (stored in parentDom._children)
  2. Diffs the new tree against the old one
  3. Only updates the parts that changed
  4. Calls update lifecycle methods
Preact automatically detects if you’re rendering into a container that already has a Preact app and performs an efficient update.

Replacing content

When you render into a container, Preact replaces any existing content:
The <p>Loading...</p> is completely replaced by the rendered content.

Hydration

Hydration is the process of attaching Preact to server-rendered HTML instead of replacing it (src/render.js:66):

When to use hydrate

Use hydrate() when:
  • You’re using server-side rendering (SSR)
  • The DOM already contains the rendered HTML
  • You want to attach event listeners and make it interactive

Hydration example

The component tree passed to hydrate() must match the server-rendered HTML exactly, or Preact will log warnings.

Rendering process

Here’s what happens when you call render():

Step-by-step breakdown

  1. Prepare the VNode - The component is wrapped in a Fragment
  2. Find previous tree - Check if this container was rendered before
  3. Diff - Compare new and old VNode trees
  4. Update DOM - Apply minimal changes to real DOM
  5. Commit - Make all DOM changes visible at once
  6. Effects - Run refs, lifecycle callbacks, etc.

Real-world example

Here’s a complete example from Preact’s demo (demo/index.jsx:197):
This example:
  • Imports render from Preact
  • Defines an App component
  • Renders it into document.body
  • Sets up client-side routing

Multiple render calls

You can call render() multiple times on the same container to update the UI:
Each call to render() on the same container performs an efficient diff and only updates what changed.

Unmounting

To unmount a component tree, render null:
This:
  • Calls componentWillUnmount() on all components
  • Removes all DOM nodes
  • Cleans up event listeners and refs

Rendering to specific elements

You can render multiple independent Preact apps on the same page:
Each render is independent and maintains its own state.

Rendering fragments

You can render fragments directly:
This renders both elements as siblings inside the container.

Performance considerations

Avoid rendering to document.body

Rendering directly to document.body can interfere with browser extensions and dev tools:

Reuse containers

When updating, always render to the same container:

Error boundaries

Wrap your render in a try-catch for error handling:
For better error handling, consider using error boundary components that catch errors in their child components.