# Preact Documentation This file contains comprehensive documentation for Preact v10, a fast 3kB alternative to React with the same modern API. Preact is a fast, lightweight alternative to React that provides the same modern API in a much smaller package. This documentation covers all aspects of Preact v10, including components, hooks, server-side rendering, TypeScript support, and more. --- ## Introduction **Description:** How to get started with Preact. We'll learn how to setup the tooling (if any) and get going with writing an application ### Getting Started New to Preact? New to Virtual DOM? Check out the [tutorial](/tutorial). This guide helps you get up and running to start developing Preact apps, using 3 popular options. If you're new to Preact, we recommend starting with [Vite](#create-a-vite-powered-preact-app). #### No build tools route Preact is packaged to be used directly in the browser, and doesn't require any build or tools: ```html ``` The primary drawback of developing this way is the lack of JSX, which requires a build step. An ergonomic and performant alternative to JSX is documented in the next section. ##### Alternatives to JSX Writing raw `h` or `createElement` calls can be tedious. JSX has the advantage of looking similar to HTML, which makes it easier to understand for many developers in our experience. JSX requires a build step though, so we highly recommend an alternative called [HTM][htm]. [HTM][htm] is a JSX-like syntax that works in standard JavaScript. Instead of requiring a build step, it uses JavaScript's own [Tagged Templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) syntax, which was added in 2015 and is supported in [all modern browsers](https://caniuse.com/#feat=template-literals). This is an increasingly popular way to write Preact apps, since there are fewer moving parts to understand than a traditional front-end build tooling setup. ```html ``` > **Tip:** HTM also provides a convenient single-import Preact version: > > `import { html, render } from 'https://esm.sh/htm/preact/standalone'` For a more scalable solution, see [Import Maps -- Basic Usage](/guide/v10/no-build-workflows#basic-usage), and for more information on HTM, check out its [documentation][htm]. [htm]: https://github.com/developit/htm #### Create a Vite-Powered Preact App [Vite](https://vitejs.dev) has become an incredibly popular tool for building applications across many frameworks in the past couple of years, and Preact is no exception. It's built upon popular tooling like ES modules, Rollup, and ESBuild. Vite, through our initializer or their Preact template, requires no configuration or prior knowledge to get started and this simplicity makes it a very popular way to use Preact. To get up and running with Vite quickly, you can use our initializer `create-preact`. This is an interactive command-line interface (CLI) app that can be run in the terminal on your machine. Using it, you can create a new application by running the following: ```bash npm init preact ``` This will walk you through creating a new Preact app and gives you some options such as TypeScript, routing (via `preact-iso`), and ESLint support. > **Tip:** None of these decisions need to be final, you can always add or remove them from your project later if you change your mind. ##### Getting ready for development Now we're ready to start our application. To start a development server, run the following command inside your newly generated project folder: ```bash # Go into the generated project folder cd my-preact-app # Start a development server npm run dev ``` Once the server has started, it will print a local development URL to open in your browser. Now you're ready to start coding your app! ##### Making a production build There comes a time when you need to deploy your app somewhere. Vite ships with a handy `build` command which will generate a highly-optimized production build. ```bash npm run build ``` Upon completion, you'll have a new `dist/` folder which can be deployed directly to a server. > For a full list of all available commands and their options, check out the [Vite CLI Documentation](https://vitejs.dev/guide/cli.html). #### Integrating Into An Existing Pipeline If you already have an existing tooling pipeline set up, it's very likely that this includes a bundler. The most popular choices are [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) or [parcel](https://parceljs.org/). Preact works out of the box with all of them, no major changes needed! ##### Setting up JSX To transpile JSX, you need a Babel plugin that converts it to valid JavaScript code. The one we all use is [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). Once installed, you need to specify the function for JSX that should be used: ```json { "plugins": [ [ "@babel/plugin-transform-react-jsx", { "pragma": "h", "pragmaFrag": "Fragment" } ] ] } ``` > [Babel](https://babeljs.io/) has some of the best documentation out there. We highly recommend checking it out for questions surrounding Babel and how to set it up. ##### Aliasing React to Preact At some point, you'll probably want to make use of the vast React ecosystem. Libraries and Components originally written for React work seamlessly with our compatibility layer. To make use of it, we need to point all `react` and `react-dom` imports to Preact. This step is called _aliasing._ > **Note:** If you're using Vite (via `@preact/preset-vite`), Preact CLI, or WMR, these aliases are automatically handled for you by default. ###### Aliasing in Webpack To alias any package in Webpack, you need to add the `resolve.alias` section to your config. Depending on the configuration you're using, this section may already be present, but missing the aliases for Preact. ```js const config = { //...snip resolve: { alias: { react: 'preact/compat', 'react-dom/test-utils': 'preact/test-utils', 'react-dom': 'preact/compat', // Must be below test-utils 'react/jsx-runtime': 'preact/jsx-runtime' } } }; ``` ###### Aliasing in Node When running in Node, bundler aliases (Webpack, Rollup, etc.) will not work, as can be seen in NextJS. To fix this, we can use aliases directly in our `package.json`: ```json { "dependencies": { "react": "npm:@preact/compat", "react-dom": "npm:@preact/compat" } } ``` ###### Aliasing in Parcel Parcel uses the standard `package.json` file to read configuration options under an `alias` key. ```json { "alias": { "react": "preact/compat", "react-dom/test-utils": "preact/test-utils", "react-dom": "preact/compat", "react/jsx-runtime": "preact/jsx-runtime" } } ``` ###### Aliasing in Rollup To alias within Rollup, you'll need to install [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias). The plugin will need to be placed before your [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve) ```js import alias from '@rollup/plugin-alias'; module.exports = { plugins: [ alias({ entries: [ { find: 'react', replacement: 'preact/compat' }, { find: 'react-dom/test-utils', replacement: 'preact/test-utils' }, { find: 'react-dom', replacement: 'preact/compat' }, { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' } ] }) ] }; ``` ###### Aliasing in Jest [Jest](https://jestjs.io/) allows the rewriting of module paths similar to bundlers. These rewrites are configured using regular expressions in your Jest configuration: ```json { "moduleNameMapper": { "^react$": "preact/compat", "^react-dom/test-utils$": "preact/test-utils", "^react-dom$": "preact/compat", "^react/jsx-runtime$": "preact/jsx-runtime" } } ``` ###### Aliasing in TypeScript TypeScript, even when used alongside a bundler, has its own process of resolving types. In order to ensure Preact's types are used in place of React's, you will want to add the following configuration to your `tsconfig.json` (or `jsconfig.json`): ```json { "compilerOptions": { ... "skipLibCheck": true, "baseUrl": "./", "paths": { "react": ["./node_modules/preact/compat/"], "react/jsx-runtime": ["./node_modules/preact/jsx-runtime"], "react-dom": ["./node_modules/preact/compat/"], "react-dom/*": ["./node_modules/preact/compat/*"] } } } ``` Additionally, you may want to enable `skipLibCheck` as we do in the example above. Some React libraries make use of types that may not be provided by `preact/compat` (though we do our best to fix these), and as such, these libraries could be the source of TypeScript compilation errors. By setting `skipLibCheck`, you can tell TS that it doesn't need to do a full check of all `.d.ts` files (usually these are limited to your libraries in `node_modules`) which will fix these errors. ###### Aliasing with Import Maps ```html ``` See also [Import Maps -- Recipes and Common Patterns](/guide/v10/no-build-workflows#recipes-and-common-patterns) for more examples. ------ **Description:** New features and changes in Preact X ### What's new in Preact X Preact X is a huge step forward from Preact 8.x. We've rethought every bit and byte of our code and added a plethora of major features in the process. Same goes for compatibility enhancements to support more third-party libraries. In a nutshell Preact X is what we always wanted Preact to be: A tiny, fast and feature-packed library. And speaking of size, you'll be happy to hear that all the new features and improved rendering fit into the same size footprint as `8.x`! #### Fragments `Fragments` are a major new feature of Preact X, and one of the main motivations for rethinking Preact's architecture. They are a special kind of component that renders children elements inline with their parent, without an extra wrapping DOM element. On top of that they allow you to return multiple nodes from `render`. [Fragment docs →](/guide/v10/components#fragments) ```jsx function Foo() { return ( <>
A
B
); } ``` #### componentDidCatch We all wish errors wouldn't happen in our applications, but sometimes they do. With `componentDidCatch`, it's now possible to catch and handle any errors that occur within lifecycle methods like `render`, including exceptions deep in the component tree. This can be used to display user-friendly error messages, or write a log entry to an external service in case something goes wrong. [Lifecycle docs →](/guide/v10/components#error-boundaries) ```jsx class Catcher extends Component { state = { errored: false }; componentDidCatch(error) { this.setState({ errored: true }); } render(props, state) { if (state.errored) { return

Something went badly wrong

; } return props.children; } } ``` #### Hooks `Hooks` are a new way to make sharing logic easier between components. They represent an alternative to the existing class-based component API. In Preact they live inside an addon which can be imported via `preact/hooks` [Hooks Docs →](/guide/v10/hooks) ```jsx function Counter() { const [value, setValue] = useState(0); const increment = useCallback(() => setValue(value + 1), [value]); return (
Counter: {value}
); } ``` #### createContext The `createContext`-API is a true successor for `getChildContext()`. Whereas `getChildContext` is fine when you're absolutely sure to never change a value, it falls apart as soon as a component in-between the provider and consumer blocks an update via `shouldComponentUpdate` when it returns `false`. With the new context API this problem is now a thing of the past. It is a true pub/sub solution to deliver updates deep down the tree. [createContext Docs →](/guide/v10/context#createcontext) ```jsx const Theme = createContext('light'); function ThemedButton(props) { return ( {theme =>
Active theme: {theme}
}
); } function App() { return ( ); } ``` #### CSS Custom Properties Sometimes it's the little things that make a huge difference. With the recent advancements in CSS you can leverage [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) for styling: ```jsx function Foo(props) { return
{props.children}
; } ``` #### Compat lives in core Although we were always keen on adding new features and pushing Preact forward, the `preact-compat` package didn't receive as much love. Up until now it has lived in a separate repository making it harder to coordinate large changes spanning Preact and the compatibility layer. By moving compat into the same package as Preact itself, there's nothing extra to install in order to use libraries from the React ecosystem. The compatibility layer is now called [preact/compat](/guide/v10/differences-to-react#features-exclusive-to-preactcompat), and has learned several new tricks such as `forwardRef`, `memo` and countless compatibility improvements. ```js // Preact 8.x import React from 'preact-compat'; // Preact X import React from 'preact/compat'; ``` #### Many compatibility fixes These are too many to list, but we've grown bounds and leaps on the compatibility front with libraries from the React ecosystem. We specifically made sure to include several popular packages in our testing process to make sure that we can guarantee full support for them. If you came across a library that didn't work well with Preact 8, you should give it another go with X. The chances are high that everything works as expected ;) ------ **Description:** Upgrade your Preact 8.x application to Preact X ### Upgrading from Preact 8.x This document is intended to guide you through upgrading an existing Preact 8.x application to Preact X and is divided in 3 main sections Preact X brings many new exciting features such as `Fragments`, `hooks` and much improved compatibility with the React ecosystem. We tried to keep any breaking changes to the minimum possible, but couldn't eliminate all of them completely without compromising on our feature set. #### Upgrading dependencies _Note: Throughout this guide we'll be using the `npm` client and the commands should be easily applicable to other package managers such as `yarn`._ Let's begin! First install Preact X: ```bash npm install preact ``` Because compat has moved to core, there is no need for `preact-compat` anymore. Remove it with: ```bash npm remove preact-compat ``` ##### Updating preact-related libraries To guarantee a stable ecosystem for our users (especially for our enterprise users) we've released major version updates to Preact X related libraries. If you're using `preact-render-to-string` you need to update it to the version that works with X. | Library | Preact 8.x | Preact X | | ------------------------- | ---------- | -------- | | `preact-render-to-string` | 4.x | 5.x | | `preact-router` | 2.x | 3.x | | `preact-jsx-chai` | 2.x | 3.x | | `preact-markup` | 1.x | 2.x | ##### Compat has moved to core To make third-party React libraries work with Preact we ship a **compat**ibility layer that can be imported via `preact/compat`. It was previously available as a separate package, but to make coordination easier we've moved it into the core repository. So you'll need to change existing import or alias declarations from `preact-compat` to `preact/compat` (note the slash). Be careful not to introduce any spelling errors here. A common one seems to be to write `compact` instead of `compat`. If you're having trouble with that, think of `compat` as the `compatibility` layer for react. That's where the name is coming from. ##### Third party libraries Due to the nature of the breaking changes, some existing libraries may cease to work with X. Most of them have been updated already following our beta schedule but you may encounter one where this is not the case. ###### preact-redux `preact-redux` is one of such libraries that hasn't been updated yet. The good news is that `preact/compat` is much more React-compliant and works out of the box with the React bindings called `react-redux`. Switching to it will resolve the situation. Make sure that you've aliased `react` and `react-dom` to `preact/compat` in your bundler. 1. Remove `preact-redux` 2. Install `react-redux` ###### mobx-preact Due to our increased compatibility with the react-ecosystem this package isn't needed anymore. Use `mobx-react` instead. 1. Remove `mobx-preact` 2. Install `mobx-react` ###### styled-components Preact 8.x only worked up to `styled-components@3.x`. With Preact X this barrier is no more and we work with the latest version of `styled-components`. Make sure that you've [aliased react to preact](/guide/v10/getting-started#aliasing-react-to-preact) correctly. ###### preact-portal The `Portal` component is now part of `preact/compat`. 1. Remove `preact-portal` 2. Import `createPortal` from `preact/compat` #### Getting your code ready ##### Using named exports To better support tree-shaking we don't ship with a `default` export in preact core anymore. The advantage of this approach is that only the code you need will be included in your bundle. ```js // Preact 8.x import Preact from 'preact'; // Preact X import * as preact from 'preact'; // Preferred: Named exports (works in 8.x and Preact X) import { h, Component } from 'preact'; ``` _Note: This change doesn't affect `preact/compat`. It still has both named and a default export to remain compatible with react._ ##### `render()` always diffs existing children In Preact 8.x, the calls to `render()` would always append the elements to the container. ```jsx // Existing markup:
hello
; render(

foo

, document.body); render(

bar

, document.body); // Preact 8.x output:
hello

foo

bar

; ``` In order to diff existing children in Preact 8, an existing DOM node had to be provided. ```jsx // Existing markup:
hello
; let element; element = render(

foo

, document.body); element = render(

bar

, document.body, element); // Preact 8.x output:
hello

bar

; ``` In Preact X, `render()` always diffs DOM children inside of the container. So if your container contains DOM that was not rendered by Preact, Preact will try to diff it with the elements you pass it. This new behavior more closely matches the behavior of other VDOM libraries. ```jsx // Existing markup:
hello
; render(

foo

, document.body); render(

bar

, document.body); // Preact X output:

bar

hello
; ``` If you are looking for behavior that exactly matches how React's `render` method works, use the `render` method exported by `preact/compat`. ##### `props.children` is not always an `array` In Preact X we can't guarantee `props.children` to always be of type `array` anymore. This change was necessary to resolve parsing ambiguities in regards to `Fragments` and components that return an `array` of children. In most cases you may not even notice it. Only in places where you'll use array methods on `props.children` directly need to be wrapped with `toChildArray`. This function will always return an array. ```jsx // Preact 8.x function Foo(props) { // `.length` is an array method. In Preact X when `props.children` is not an // array, this line will throw an exception const count = props.children.length; return
I have {count} children
; } // Preact X import { toChildArray } from 'preact'; function Foo(props) { const count = toChildArray(props.children).length; return
I have {count} children
; } ``` ##### Don't access `this.state` synchronously In Preact X the state of a component will no longer be mutated synchronously. This means that reading from `this.state` right after a `setState` call will return the previous values. Instead you should use a callback function to modify state that depends on the previous values. ```jsx this.state = { counter: 0 }; // Preact 8.x this.setState({ counter: this.state.counter + 1 }); // Preact X this.setState(prevState => { // Alternatively return `null` here to abort the state update return { counter: prevState.counter + 1 }; }); ``` ##### `dangerouslySetInnerHTML` will skip diffing of children When a `vnode` has the property `dangerouslySetInnerHTML` set Preact will skip diffing the `vnode's` children. ```jsx
I will be skipped

So will I

``` #### Notes for library authors This section is intended for library authors who are maintaining packages to be used with Preact X. You can safely skip this section if you're not writing one. ##### The `VNode` shape has changed We renamed/moved the following properties: - `attributes` -> `props` - `nodeName` -> `type` - `children` -> `props.children` As much as we tried, we always ran into edge-cases with third-party libraries written for react. This change to our `vnode` shape removed many difficult to spot bugs and makes our `compat` code a lot cleaner. ##### Adjacent text nodes are not joined anymore In Preact 8.x we had this feature where we would join adjacent text notes as an optimization. This doesn't hold true for X anymore because we're not diffing directly against the dom anymore. In fact we noticed that it hurt performance in X which is why we removed it. Take the following example: ```jsx // Preact 8.x console.log(
foo{'bar'}
); // Logs a structure like this: // div // text // Preact X console.log(
foo{'bar'}
); // Logs a structure like this: // div // text // text ``` ------ ## Essentials **Description:** Components are the heart of any Preact application. Learn how to create them and use them to compose UIs together ### Components Components represent the basic building block in Preact. They are fundamental in making it easy to build complex UIs from little building blocks. They're also responsible for attaching state to our rendered output. There are two kinds of components in Preact, which we'll talk about in this guide. #### Functional Components Functional components are plain functions that receive `props` as the first argument. The function name **must** start with an uppercase letter in order for them to work in JSX. ```jsx import { render } from 'preact'; function MyComponent(props) { return
My name is {props.name}.
; } // Usage const App = ; // Renders:
My name is John Doe.
render(App, document.body); ``` > Note in earlier versions they were known as `"Stateless Components"`. This doesn't hold true anymore with the [hooks-addon](/guide/v10/hooks). #### Class Components Class components can have state and lifecycle methods. The latter are special methods, that will be called when a component is attached to the DOM or destroyed for example. Here we have a simple class component called `` that displays the current time: ```jsx import { Component, render } from 'preact'; class Clock extends Component { constructor() { super(); this.state = { time: Date.now() }; } // Lifecycle: Called whenever our component is created componentDidMount() { // update time every second this.timer = setInterval(() => { this.setState({ time: Date.now() }); }, 1000); } // Lifecycle: Called just before our component will be destroyed componentWillUnmount() { // stop when not renderable clearInterval(this.timer); } render() { let time = new Date(this.state.time).toLocaleTimeString(); return {time}; } } render(, document.getElementById('app')); ``` ##### Lifecycle Methods In order to have the clock's time update every second, we need to know when `` gets mounted to the DOM. _If you've used HTML5 Custom Elements, this is similar to the `attachedCallback` and `detachedCallback` lifecycle methods._ Preact invokes the following lifecycle methods if they are defined for a Component: | Lifecycle method | When it gets called | | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | `componentWillMount()` | (deprecated) before the component gets mounted to the DOM | | `componentDidMount()` | after the component gets mounted to the DOM | | `componentWillUnmount()` | prior to removal from the DOM | | `componentWillReceiveProps(nextProps, nextContext)` | before new props get accepted _(deprecated)_ | | `getDerivedStateFromProps(nextProps, prevState)` | just before `shouldComponentUpdate`. Return object to update state or `null` to skip update. Use with care. | | `shouldComponentUpdate(nextProps, nextState, nextContext)` | before `render()`. Return `false` to skip render | | `componentWillUpdate(nextProps, nextState, nextContext)` | before `render()` _(deprecated)_ | | `getSnapshotBeforeUpdate(prevProps, prevState)` | called just before `render()`. return value is passed to `componentDidUpdate`. | | `componentDidUpdate(prevProps, prevState, snapshot)` | after `render()` | Here's a visual overview of how they relate to each other (originally posted in [a tweet](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509) by Dan Abramov): ![Diagram of component lifecycle methods](/guide/components-lifecycle-diagram.png) ##### Error Boundaries An error boundary is a component that implements either `componentDidCatch()` or the static method `getDerivedStateFromError()` (or both). These are special methods that allow you to catch any errors that happen during rendering and are typically used to provide nicer error messages or other fallback content and save information for logging purposes. It's important to note that error boundaries cannot catch all errors and those thrown in event handlers or asynchronous code (like a `fetch()` call) need to be handled separately. When an error is caught, we can use these methods to react to any errors and display a nice error message or any other fallback content. ```jsx import { Component, render } from 'preact'; class ErrorBoundary extends Component { constructor() { super(); this.state = { errored: false }; } static getDerivedStateFromError(error) { return { errored: true }; } componentDidCatch(error, errorInfo) { errorReportingService(error, errorInfo); } render(props, state) { if (state.errored) { return

Something went badly wrong

; } return props.children; } } render(, document.getElementById('app')); ``` #### Fragments A `Fragment` allows you to return multiple elements at once. They solve the limitation of JSX where every "block" must have a single root element. You'll often encounter them in combination with lists, tables or with CSS flexbox where any intermediate element would otherwise affect styling. ```jsx import { Fragment, render } from 'preact'; function TodoItems() { return (
  • A
  • B
  • C
  • ); } const App = (
    • D
    ); render(App, container); // Renders: //
      //
    • A
    • //
    • B
    • //
    • C
    • //
    • D
    • //
    ``` Note that most modern transpilers allow you to use a shorter syntax for `Fragments`. The shorter one is a lot more common and is the one you'll typically encounter. ```jsx // This: const Foo = foo; // ...is the same as this: const Bar = <>foo; ``` You can also return arrays from your components: ```jsx function Columns() { return [Hello, World]; } ``` Don't forget to add keys to `Fragments` if you create them in a loop: ```jsx function Glossary(props) { return (
    {props.items.map(item => ( // Without a key, Preact has to guess which elements have // changed when re-rendering.
    {item.term}
    {item.description}
    ))}
    ); } ``` ------ **Description:** Hooks in Preact allow you to compose behaviours together and re-use that logic in different components ### Hooks The Hooks API is an alternative way to write components in Preact. Hooks allow you to compose state and side effects, reusing stateful logic much more easily than with class components. If you've worked with class components in Preact for a while, you may be familiar with patterns like "render props" and "higher order components" that try to solve these challenges. These solutions have tended to make code harder to follow and more abstract. The hooks API makes it possible to neatly extract the logic for state and side effects, and also simplifies unit testing that logic independently from the components that rely on it. Hooks can be used in any component, and avoid many pitfalls of the `this` keyword relied on by the class components API. Instead of accessing properties from the component instance, hooks rely on closures. This makes them value-bound and eliminates a number of stale data problems that can occur when dealing with asynchronous state updates. There are two ways to import hooks: from `preact/hooks` or `preact/compat`. #### Introduction The easiest way to understand hooks is to compare them to equivalent class-based Components. We'll use a simple counter component as our example, which renders a number and a button that increases it by one: ```jsx import { render, Component } from 'preact'; class Counter extends Component { state = { value: 0 }; increment = () => { this.setState(prev => ({ value: prev.value + 1 })); }; render(props, state) { return (

    Counter: {state.value}

    ); } } render(, document.getElementById('app')); ``` Now, here's an equivalent function component built with hooks: ```jsx import { useState, useCallback } from 'preact/hooks'; import { render } from 'preact'; function Counter() { const [value, setValue] = useState(0); const increment = useCallback(() => { setValue(value + 1); }, [value]); return (

    Counter: {value}

    ); } render(, document.getElementById('app')); ``` At this point they seem pretty similar, however we can further simplify the hooks version. Let's extract the counter logic into a custom hook, making it easily reusable across components: ```jsx import { useState, useCallback } from 'preact/hooks'; import { render } from 'preact'; function useCounter() { const [value, setValue] = useState(0); const increment = useCallback(() => { setValue(value + 1); }, [value]); return { value, increment }; } // First counter function CounterA() { const { value, increment } = useCounter(); return (

    Counter A: {value}

    ); } // Second counter which renders a different output. function CounterB() { const { value, increment } = useCounter(); return (

    Counter B: {value}

    I'm a nice counter

    ); } render(
    , document.getElementById('app') ); ``` Note that both `CounterA` and `CounterB` are completely independent of each other. They both use the `useCounter()` custom hook, but each has its own instance of that hook's associated state. > Thinking this looks a little strange? You're not alone! > > It took many of us a while to grow accustomed to this approach. #### The dependency argument Many hooks accept an argument that can be used to limit when a hook should be updated. Preact inspects each value in a dependency array and checks to see if it has changed since the last time a hook was called. When the dependency argument is not specified, the hook is always executed. In our `useCounter()` implementation above, we passed an array of dependencies to `useCallback()`: ```jsx function useCounter() { const [value, setValue] = useState(0); const increment = useCallback(() => { setValue(value + 1); }, [value]); // <-- the dependency array return { value, increment }; } ``` Passing `value` here causes `useCallback` to return a new function reference whenever `value` changes. This is necessary in order to avoid "stale closures", where the callback would always reference the first render's `value` variable from when it was created, causing `increment` to always set a value of `1`. > This creates a new `increment` callback every time `value` changes. > For performance reasons, it's often better to use a [callback](#usestate) to update state values rather than retaining the current value using dependencies. #### Stateful hooks Here we'll see how we can introduce stateful logic into functional components. Prior to the introduction of hooks, class components were required anywhere state was needed. ##### useState This hook accepts an argument, this will be the initial state. When invoked this hook returns an array of two variables. The first being the current state and the second being the setter for our state. Our setter behaves similar to the setter of our classic state. It accepts a value or a function with the currentState as argument. When you call the setter and the state is different, it will trigger a rerender starting from the component where that useState has been used. ```jsx import { render } from 'preact'; import { useState } from 'preact/hooks'; const Counter = () => { const [count, setCount] = useState(0); const increment = () => setCount(count + 1); // You can also pass a callback to the setter const decrement = () => setCount(currentCount => currentCount - 1); return (

    Count: {count}

    ); }; render(, document.getElementById('app')); ``` > When our initial state is expensive it's better to pass a function instead of a value. ##### useReducer The `useReducer` hook has a close resemblance to [redux](https://redux.js.org/). Compared to [useState](#usestate) it's easier to use when you have complex state logic where the next state depends on the previous one. ```jsx import { render } from 'preact'; import { useReducer } from 'preact/hooks'; const initialState = 0; const reducer = (state, action) => { switch (action) { case 'increment': return state + 1; case 'decrement': return state - 1; case 'reset': return 0; default: throw new Error('Unexpected action'); } }; function Counter() { // Returns the current state and a dispatch function to // trigger an action const [count, dispatch] = useReducer(reducer, initialState); return (
    {count}
    ); } render(, document.getElementById('app')); ``` #### Memoization In UI programming there is often some state or result that's expensive to calculate. Memoization can cache the results of that calculation allowing it to be reused when the same input is used. ##### useMemo With the `useMemo` hook we can memoize the results of that computation and only recalculate it when one of the dependencies changes. ```jsx const memoized = useMemo( () => expensive(a, b), // Only re-run the expensive function when any of these // dependencies change [a, b] ); ``` > Don't run any effectful code inside `useMemo`. Side-effects belong in `useEffect`. ##### useCallback The `useCallback` hook can be used to ensure that the returned function will remain referentially equal for as long as no dependencies have changed. This can be used to optimize updates of child components when they rely on referential equality to skip updates (e.g. `shouldComponentUpdate`). ```jsx const onClick = useCallback(() => console.log(a, b), [a, b]); ``` > Fun fact: `useCallback(fn, deps)` is equivalent to `useMemo(() => fn, deps)`. #### Refs **Ref**erences are stable, local values that persist across rerenders but don't cause rerenders themselves. See [Refs](/guide/v10/refs) for more information & examples. ##### useRef To create a stable reference to a DOM node or a value that persists between renders, we can use the `useRef` hook. It works similarly to [createRef](/guide/v10/refs#createref). ```jsx import { useRef } from 'preact/hooks'; import { render } from 'preact'; function Foo() { // Initialize useRef with an initial value of `null` const input = useRef(null); const onClick = () => input.current && input.current.focus(); return ( <> ); } render(, document.getElementById('app')); ``` > Be careful not to confuse `useRef` with `createRef`. ##### useImperativeHandle To mutate a ref that is passed into a child component we can use the `useImperativeHandle` hook. It takes three arguments: the ref to mutate, a function to execute that will return the new ref value, and a dependency array to determine when to rerun. ```jsx import { render } from 'preact'; import { useRef, useImperativeHandle, useState } from 'preact/hooks'; function MyInput({ inputRef }) { const ref = useRef(null); useImperativeHandle( inputRef, () => { return { // Only expose `.focus()`, don't give direct access to the DOM node focus() { ref.current.focus(); } }; }, [] ); return ( ); } function App() { const inputRef = useRef(null); const handleClick = () => { inputRef.current.focus(); }; return (
    ); } render(, document.getElementById('app')); ``` #### useContext To access context in a functional component we can use the `useContext` hook, without any higher-order or wrapper components. The first argument must be the context object that's created from a `createContext` call. ```jsx import { render, createContext } from 'preact'; import { useContext } from 'preact/hooks'; const OtherComponent = props => props.children; const Theme = createContext('light'); function DisplayTheme() { const theme = useContext(Theme); return

    Active theme: {theme}

    ; } // ...later function App() { return ( ); } render(, document.getElementById('app')); ``` #### Side-Effects Side-Effects are at the heart of many modern Apps. Whether you want to fetch some data from an API or trigger an effect on the document, you'll find that the `useEffect` fits nearly all your needs. It's one of the main advantages of the hooks API, that it reshapes your mind into thinking in effects instead of a component's lifecycle. ##### useEffect As the name implies, `useEffect` is the main way to trigger various side-effects. You can even return a cleanup function from your effect if one is needed. ```jsx useEffect(() => { // Trigger your effect return () => { // Optional: Any cleanup code }; }, []); ``` We'll start with a `Title` component which should reflect the title to the document, so that we can see it in the address bar of our tab in our browser. ```jsx function PageTitle(props) { useEffect(() => { document.title = props.title; }, [props.title]); return

    {props.title}

    ; } ``` The first argument to `useEffect` is an argument-less callback that triggers the effect. In our case we only want to trigger it, when the title really has changed. There'd be no point in updating it when it stayed the same. That's why we're using the second argument to specify our [dependency-array](#the-dependency-argument). But sometimes we have a more complex use case. Think of a component which needs to subscribe to some data when it mounts and needs to unsubscribe when it unmounts. This can be accomplished with `useEffect` too. To run any cleanup code we just need to return a function in our callback. ```jsx import { useState, useEffect } from 'preact/hooks'; import { render } from 'preact'; // Component that will always display the current window width function WindowWidth(props) { const [width, setWidth] = useState(0); function onResize() { setWidth(window.innerWidth); } useEffect(() => { window.addEventListener('resize', onResize); return () => window.removeEventListener('resize', onResize); }, []); return

    Window width: {width}

    ; } render(, document.getElementById('app')); ``` > The cleanup function is optional. If you don't need to run any cleanup code, you don't need to return anything in the callback that's passed to `useEffect`. ##### useLayoutEffect Similar to [`useEffect`](#useeffect), `useLayoutEffect` is used to trigger side-effects but it will do so as soon as the component is diffed and before the browser has a chance to repaint. Commonly used for measuring DOM elements, this allows you to avoid flickering or pop-in that may occur if you use `useEffect` for such tasks. ```jsx import { useLayoutEffect, useRef } from 'preact/hooks'; function App() { const hintRef = useRef(null); useLayoutEffect(() => { const hintWidth = hintRef.current.getBoundingClientRect().width; // We might use this width to position and center the hint on the screen, like so: hintRef.current.style.left = `${(window.innerWidth - hintWidth) / 2}px`; }, []); return (

    This is a hint

    ); } ``` ##### useErrorBoundary Whenever a child component throws an error you can use this hook to catch it and display a custom error UI to the user. ```jsx // error = The error that was caught or `undefined` if nothing errored. // resetError = Call this function to mark an error as resolved. It's // up to your app to decide what that means and if it is possible // to recover from errors. const [error, resetError] = useErrorBoundary(); ``` For monitoring purposes it's often incredibly useful to notify a service of any errors. For that we can leverage an optional callback and pass that as the first argument to `useErrorBoundary`. ```jsx const [error] = useErrorBoundary(error => callMyApi(error.message)); ``` A full usage example may look like this: ```jsx const App = props => { const [error, resetError] = useErrorBoundary(error => callMyApi(error.message) ); // Display a nice error message if (error) { return (

    {error.message}

    ); } else { return
    {props.children}
    ; } }; ``` > If you've been using the class based component API in the past, then this hook is essentially an alternative to the [componentDidCatch](/guide/v10/whats-new/#componentdidcatch) lifecycle method. > This hook was introduced with Preact 10.2.0. #### Utility hooks ##### useId This hook will generate a unique identifier for each invocation and guarantees that these will be consistent when rendering both [on the server](/guide/v10/server-side-rendering) and the client. A common use case for consistent IDs are forms, where `