Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/preactjs/preact/llms.txt

Use this file to discover all available pages before exploring further.

Components are the building blocks of Preact applications. They let you split your UI into independent, reusable pieces.

Component types

Preact supports two types of components:
Functional components are simple JavaScript functions that accept props and return JSX.
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}
This is the recommended approach for most components. They are simpler, easier to test, and work seamlessly with hooks.

The Component class

Preact exports a BaseComponent class (aliased as Component) that provides core functionality for class-based components. Here’s how it’s defined in src/component.js:19:
export function BaseComponent(props, context) {
  this.props = props;
  this.context = context;
  this._bits = 0;
}
The Component class provides two key methods:

setState()

Updates component state and schedules a re-render:
BaseComponent.prototype.setState = function (update, callback) {
  let s;
  if (this._nextState != NULL && this._nextState != this.state) {
    s = this._nextState;
  } else {
    s = this._nextState = assign({}, this.state);
  }

  if (typeof update == 'function') {
    update = update(assign({}, s), this.props);
  }

  if (update) {
    assign(s, update);
  } else {
    return;
  }

  if (this._vnode) {
    if (callback) {
      this._stateCallbacks.push(callback);
    }
    enqueueRender(this);
  }
};

forceUpdate()

Immediately triggers a re-render, bypassing shouldComponentUpdate():
BaseComponent.prototype.forceUpdate = function (callback) {
  if (this._vnode) {
    this._bits |= COMPONENT_FORCE;
    if (callback) this._renderCallbacks.push(callback);
    enqueueRender(this);
  }
};

Props

Props (short for “properties”) are arguments passed to components. They are read-only and flow down from parent to child.
function Welcome({ name, age }) {
  return (
    <div>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
    </div>
  );
}

// Usage
<Welcome name="Alice" age={30} />

Props in class components

In class components, props are available via this.props:
import { Component } from 'preact';

class Welcome extends Component {
  render() {
    return (
      <div>
        <p>Name: {this.props.name}</p>
        <p>Age: {this.props.age}</p>
      </div>
    );
  }
}

State

State is private data managed within a component. When state changes, the component re-renders.

State in class components

Here’s a real example from Preact’s demo code (demo/todo.jsx:5):
import { Component } from 'preact';

class TodoList extends Component {
  state = { todos: [], text: '' };

  setText = e => {
    this.setState({ text: e.target.value });
  };

  addTodo = () => {
    let { todos, text } = this.state;
    todos = todos.concat({ text, id: ++counter });
    this.setState({ todos, text: '' });
  };

  render({}, { todos, text }) {
    return (
      <form onSubmit={this.addTodo} action="javascript:">
        <input value={text} onInput={this.setText} />
        <button type="submit">Add</button>
        <ul>
          {todos.map(todo => (
            <li key={todo.id}>{todo.text}</li>
          ))}
        </ul>
      </form>
    );
  }
}
The render() method can destructure both props and state from its arguments for cleaner code.

Updating state

You can pass an object or a function to setState():
this.setState({ count: 5 });
Never modify state directly. Always use setState() to ensure the component re-renders correctly.

Functional vs class components

Here’s the same component implemented both ways:
import { useState } from 'preact/hooks';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

Real-world example

Here’s a complete example from Preact’s demo showing both component types working together (demo/context.jsx:5):
import { Component, createContext } from 'preact';
const { Provider, Consumer } = createContext();

class ThemeProvider extends Component {
  state = {
    value: this.props.value
  };

  onClick = () => {
    this.setState(prev => ({
      value: prev.value === this.props.value 
        ? this.props.next 
        : this.props.value
    }));
  };

  render() {
    return (
      <div>
        <button onClick={this.onClick}>Toggle</button>
        <Provider value={this.state.value}>
          {this.props.children}
        </Provider>
      </div>
    );
  }
}

class Child extends Component {
  shouldComponentUpdate() {
    return false;
  }

  render() {
    return (
      <>
        <p>(blocked update)</p>
        {this.props.children}
      </>
    );
  }
}
This example demonstrates prop passing, state management, lifecycle methods, and component composition.

Component render queue

When you call setState() or forceUpdate(), Preact doesn’t immediately re-render the component. Instead, it adds the component to a render queue (src/component.js:185):
let rerenderQueue = [];

export function enqueueRender(c) {
  if (
    (!(c._bits & COMPONENT_DIRTY) &&
      (c._bits |= COMPONENT_DIRTY) &&
      rerenderQueue.push(c) &&
      !rerenderCount++) ||
    prevDebounce != options.debounceRendering
  ) {
    prevDebounce = options.debounceRendering;
    (prevDebounce || queueMicrotask)(process);
  }
}
This batching mechanism ensures efficient rendering by processing multiple updates together.

Build docs developers (and LLMs) love