reactjsDoc

Must Watch!



MustWatch



Getting Started

This page is an overview of the React documentation and related resources. React is a JavaScript library for building user interfaces. Learn what React is all about on our homepage or in the tutorial.

Try React

React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Whether you want to get a taste of React, add some interactivity to a simple HTML page, or start a complex React-powered app, the links in this section will help you get started.

Online Playgrounds

If you're interested in playing around with React, you can use an online code playground. Try a Hello World template on CodePen, CodeSandbox, or Stackblitz. If you prefer to use your own text editor, you can also download this HTML file, edit it, and open it from the local filesystem in your browser. It does a slow runtime code transformation, so we'd only recommend using this for simple demos.

Add React to a Website

You can add React to an HTML page in one minute. You can then either gradually expand its presence, or keep it contained to a few dynamic widgets.

Create a New React App

When starting a React project, a simple HTML page with script tags might still be the best option. It only takes a minute to set up! As your application grows, you might want to consider a more integrated setup. There are several JavaScript toolchains we recommend for larger applications. Each of them can work with little to no configuration and lets you take full advantage of the rich React ecosystem. Learn how.

Learn React

People come to React from different backgrounds and with different learning styles. Whether you prefer a more theoretical or a practical approach, we hope you'll find this section helpful. Like any unfamiliar technology, React does have a learning curve. With practice and some patience, you will get the hang of it.

First Examples

The React homepage contains a few small React examples with a live editor. Even if you don't know anything about React yet, try changing their code and see how it affects the result.

React for Beginners

If you feel that the React documentation goes at a faster pace than you're comfortable with, check out this overview of React by Tania Rascia. It introduces the most important React concepts in a detailed, beginner-friendly way. Once you're done, give the documentation another try!

React for Designers

If you're coming from a design background, these resources are a great place to get started.

JavaScript Resources

The React documentation assumes some familiarity with programming in the JavaScript language. You don't have to be an expert, but it's harder to learn both React and JavaScript at the same time. We recommend going through this JavaScript overview to check your knowledge level. It will take you between 30 minutes and an hour but you will feel more confident learning React.
Tip Whenever you get confused by something in JavaScript, MDN and javascript.info are great websites to check. There are also community support forums where you can ask for help.

Practical Tutorial

If you prefer to learn by doing, check out our practical tutorial. In this tutorial, we build a tic-tac-toe game in React. You might be tempted to skip it because you're not into building games ¡ª but give it a chance. The techniques you'll learn in the tutorial are fundamental to building any React apps, and mastering it will give you a much deeper understanding.

Step-by-Step Guide

If you prefer to learn concepts step by step, our guide to main concepts is the best place to start. Every next chapter in it builds on the knowledge introduced in the previous chapters so you won't miss anything as you go along.

Thinking in React

Many React users credit reading Thinking in React as the moment React finally ¡°clicked¡± for them. It's probably the oldest React walkthrough but it's still just as relevant.

Recommended Courses

Sometimes people find third-party books and video courses more helpful than the official documentation. We maintain a list of commonly recommended resources, some of which are free.

Advanced Concepts

Once you're comfortable with the main concepts and played with React a little bit, you might be interested in more advanced topics. This section will introduce you to the powerful, but less commonly used React features like context and refs.

API Reference

This documentation section is useful when you want to learn more details about a particular React API. For example, React.Component API reference can provide you with details on how setState() works, and what different lifecycle methods are useful for.

Glossary and FAQ

The glossary contains an overview of the most common terms you'll see in the React documentation. There is also a FAQ section dedicated to short questions and answers about common topics, including making AJAX requests, component state, and file structure.

Staying Informed

The React blog is the official source for the updates from the React team. Anything important, including release notes or deprecation notices, will be posted there first. You can also follow the @reactjs account on Twitter, but you won't miss anything essential if you only read the blog. Not every React release deserves its own blog post, but you can find a detailed changelog for every release in the CHANGELOG.md file in the React repository, as well as on the Releases page.

Versioned Documentation

This documentation always reflects the latest stable version of React. Since React 16, you can find older versions of the documentation on a separate page. Note that documentation for past versions is snapshotted at the time of the release, and isn't being continuously updated.

Something Missing?

If something is missing in the documentation or if you found some part confusing, please file an issue for the documentation repository with your suggestions for improvement, or tweet at the @reactjs account. We love hearing from you!

Add React to a Website

Use as little or as much React as you need. React has been designed from the start for gradual adoption, and you can use as little or as much React as you need. Perhaps you only want to add some ¡°sprinkles of interactivity¡± to an existing page. React components are a great way to do that. The majority of websites aren't, and don't need to be, single-page apps. With a few lines of code and no build tooling, try React in a small part of your website. You can then either gradually expand its presence, or keep it contained to a few dynamic widgets.

Add React in One Minute

In this section, we will show how to add a React component to an existing HTML page. You can follow along with your own website, or create an empty HTML file to practice. There will be no complicated tools or install requirements ¡ª to complete this section, you only need an internet connection, and a minute of your time. Optional: Download the full example (2KB zipped)

Step 1: Add a DOM Container to the HTML

First, open the HTML page you want to edit. Add an empty <div> tag to mark the spot where you want to display something with React. For example: <!-- ... existing HTML ... --> <div id="like_button_container"></div> <!-- ... existing HTML ... --> We gave this <div> a unique id HTML attribute. This will allow us to find it from the JavaScript code later and display a React component inside of it.
Tip You can place a ¡°container¡± <div> like this anywhere inside the <body> tag. You may have as many independent DOM containers on one page as you need. They are usually empty ¡ª React will replace any existing content inside DOM containers.

Step 2: Add the Script Tags

Next, add three <script> tags to the HTML page right before the closing </body> tag: <!-- ... other HTML ... --> <!-- Load React. --> <!-- Note: when deploying, replace "development.js" with "production.min.js". --> <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script> <!-- Load our React component. --> <script src="like_button.js"></script> </body> The first two tags load React. The third one will load your component code.

Step 3: Create a React Component

Create a file called like_button.js next to your HTML page. Open this starter code and paste it into the file you created.
Tip This code defines a React component called LikeButton. Don't worry if you don't understand it yet ¡ª we'll cover the building blocks of React later in our hands-on tutorial and main concepts guide. For now, let's just get it showing on the screen!
After the starter code, add two lines to the bottom of like_button.js: // ... the starter code you pasted ... const domContainer = document.querySelector('#like_button_container');ReactDOM.render(e(LikeButton), domContainer); These two lines of code find the <div> we added to our HTML in the first step, and then display our ¡°Like¡± button React component inside of it.

That's It!

There is no step four. You have just added the first React component to your website. Check out the next sections for more tips on integrating React. View the full example source code Download the full example (2KB zipped)

Tip: Reuse a Component

Commonly, you might want to display React components in multiple places on the HTML page. Here is an example that displays the ¡°Like¡± button three times and passes some data to it: View the full example source code Download the full example (2KB zipped)
Note This strategy is mostly useful while React-powered parts of the page are isolated from each other. Inside React code, it's easier to use component composition instead.

Tip: Minify JavaScript for Production

Before deploying your website to production, be mindful that unminified JavaScript can significantly slow down the page for your users. If you already minify the application scripts, your site will be production-ready if you ensure that the deployed HTML loads the versions of React ending in production.min.js: <script src="https://unpkg.com/react@17/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js" crossorigin></script> If you don't have a minification step for your scripts, here's one way to set it up.

Optional: Try React with JSX

In the examples above, we only relied on features that are natively supported by the browsers. This is why we used a JavaScript function call to tell React what to display: const e = React.createElement; // Display a "Like" <button> return e( 'button', { onClick: () => this.setState({ liked: true }) }, 'Like' ); However, React also offers an option to use JSX instead: // Display a "Like" <button> return ( <button onClick={() => this.setState({ liked: true })}> Like </button> ); These two code snippets are equivalent. While JSX is completely optional, many people find it helpful for writing UI code ¡ª both with React and with other libraries. You can play with JSX using this online converter.

Quickly Try JSX

The quickest way to try JSX in your project is to add this <script> tag to your page: <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> Now you can use JSX in any <script> tag by adding type="text/babel" attribute to it. Here is an example HTML file with JSX that you can download and play with. This approach is fine for learning and creating simple demos. However, it makes your website slow and isn't suitable for production. When you're ready to move forward, remove this new <script> tag and the type="text/babel" attributes you've added. Instead, in the next section you will set up a JSX preprocessor to convert all your <script> tags automatically.

Add JSX to a Project

Adding JSX to a project doesn't require complicated tools like a bundler or a development server. Essentially, adding JSX is a lot like adding a CSS preprocessor. The only requirement is to have Node.js installed on your computer. Go to your project folder in the terminal, and paste these two commands:
  1. Step 1: Run npm init -y (if it fails, here's a fix)
  2. Step 2: Run npm install babel-cli@6 babel-preset-react-app@3
Tip We're using npm here only to install the JSX preprocessor; you won't need it for anything else. Both React and the application code can stay as <script> tags with no changes.
Congratulations! You just added a production-ready JSX setup to your project.

Run JSX Preprocessor

Create a folder called src and run this terminal command: npx babel --watch src --out-dir . --presets react-app/prod
Note npx is not a typo ¡ª it's a package runner tool that comes with npm 5.2+. If you see an error message saying ¡°You have mistakenly installed the babel package¡±, you might have missed the previous step. Perform it in the same folder, and then try again.
Don't wait for it to finish ¡ª this command starts an automated watcher for JSX. If you now create a file called src/like_button.js with this JSX starter code, the watcher will create a preprocessed like_button.js with the plain JavaScript code suitable for the browser. When you edit the source file with JSX, the transform will re-run automatically. As a bonus, this also lets you use modern JavaScript syntax features like classes without worrying about breaking older browsers. The tool we just used is called Babel, and you can learn more about it from its documentation. If you notice that you're getting comfortable with build tools and want them to do more for you, the next section describes some of the most popular and approachable toolchains. If not ¡ª those script tags will do just fine!

Create a New React App

Use an integrated toolchain for the best user and developer experience. This page describes a few popular React toolchains which help with tasks like: The toolchains recommended on this page don't require configuration to get started.

You Might Not Need a Toolchain

If you don't experience the problems described above or don't feel comfortable using JavaScript tools yet, consider adding React as a plain <script> tag on an HTML page, optionally with JSX. This is also the easiest way to integrate React into an existing website. You can always add a larger toolchain if you find it helpful!

Recommended Toolchains

The React team primarily recommends these solutions:

Create React App

Create React App is a comfortable environment for learning React, and is the best way to start building a new single-page application in React. It sets up your development environment so that you can use the latest JavaScript features, provides a nice developer experience, and optimizes your app for production. You'll need to have Node >= 10.16 and npm >= 5.6 on your machine. To create a project, run: npx create-react-app my-app cd my-app npm start
Note npx on the first line is not a typo ¡ª it's a package runner tool that comes with npm 5.2+.
Create React App doesn't handle backend logic or databases; it just creates a frontend build pipeline, so you can use it with any backend you want. Under the hood, it uses Babel and webpack, but you don't need to know anything about them. When you're ready to deploy to production, running npm run build will create an optimized build of your app in the build folder. You can learn more about Create React App from its README and the User Guide.

Next.js

Next.js is a popular and lightweight framework for static and server rendered applications built with React. It includes styling and routing solutions out of the box, and assumes that you're using Node.js as the server environment. Learn Next.js from its official guide.

Gatsby

Gatsby is the best way to create static websites with React. It lets you use React components, but outputs pre-rendered HTML and CSS to guarantee the fastest load time. Learn Gatsby from its official guide and a gallery of starter kits.

More Flexible Toolchains

The following toolchains offer more flexibility and choice. We recommend them to more experienced users:

Creating a Toolchain from Scratch

A JavaScript build toolchain typically consists of: If you prefer to set up your own JavaScript toolchain from scratch, check out this guide that re-creates some of the Create React App functionality. Don't forget to ensure your custom toolchain is correctly set up for production.

CDN Links

Both React and ReactDOM are available over a CDN. <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> The versions above are only meant for development, and are not suitable for production. Minified and optimized production versions of React are available at: <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script> To load a specific version of react and react-dom, replace 17 with the version number.

Why the crossorigin Attribute?

If you serve React from a CDN, we recommend to keep the crossorigin attribute set: <script crossorigin src="..."></script> We also recommend to verify that the CDN you are using sets the Access-Control-Allow-Origin: * HTTP header: This enables a better error handling experience in React 16 and later.

Release Channels

React relies on a thriving open source community to file bug reports, open pull requests, and submit RFCs. To encourage feedback we sometimes share special builds of React that include unreleased features.
This document will be most relevant to developers who work on frameworks, libraries, or developer tooling. Developers who use React primarily to build user-facing applications should not need to worry about our prerelease channels.
Each of React's release channels is designed for a distinct use case: All releases are published to npm, but only Latest uses semantic versioning. Prereleases (those in the Next and Experimental channels) have versions generated from a hash of their contents, e.g. 0.0.0-1022ee0ec for Next and 0.0.0-experimental-1022ee0ec for Experimental. The only officially supported release channel for user-facing applications is Latest. Next and Experimental releases are provided for testing purposes only, and we provide no guarantees that behavior won't change between releases. They do not follow the semver protocol that we use for releases from Latest. By publishing prereleases to the same registry that we use for stable releases, we are able to take advantage of the many tools that support the npm workflow, like unpkg and CodeSandbox.

Latest Channel

Latest is the channel used for stable React releases. It corresponds to the latest tag on npm. It is the recommended channel for all React apps that are shipped to real users. If you're not sure which channel you should use, it's Latest. If you're a React developer, this is what you're already using. You can expect updates to Latest to be extremely stable. Versions follow the semantic versioning scheme. Learn more about our commitment to stability and incremental migration in our versioning policy.

Next Channel

The Next channel is a prerelease channel that tracks the master branch of the React repository. We use prereleases in the Next channel as release candidates for the Latest channel. You can think of Next as a superset of Latest that is updated more frequently. The degree of change between the most recent Next release and the most recent Latest release is approximately the same as you would find between two minor semver releases. However, the Next channel does not conform to semantic versioning. You should expect occasional breaking changes between successive releases in the Next channel. Do not use prereleases in user-facing applications. Releases in Next are published with the next tag on npm. Versions are generated from a hash of the build's contents, e.g. 0.0.0-1022ee0ec.
Using the Next Channel for Integration Testing
The Next channel is designed to support integration testing between React and other projects. All changes to React go through extensive internal testing before they are released to the public. However, there are a myriad of environments and configurations used throughout the React ecosystem, and it's not possible for us to test against every single one. If you're the author of a third party React framework, library, developer tool, or similar infrastructure-type project, you can help us keep React stable for your users and the entire React community by periodically running your test suite against the most recent changes. If you're interested, follow these steps: A project that uses this workflow is Next.js. (No pun intended! Seriously!) You can refer to their CircleCI configuration as an example.

Experimental Channel

Like Next, the Experimental channel is a prerelease channel that tracks the master branch of the React repository. Unlike Next, Experimental releases include additional features and APIs that are not ready for wider release. Usually, an update to Next is accompanied by a corresponding update to Experimental. They are based on the same source revision, but are built using a different set of feature flags. Experimental releases may be significantly different than releases to Next and Latest. Do not use Experimental releases in user-facing applications. You should expect frequent breaking changes between releases in the Experimental channel. Releases in Experimental are published with the experimental tag on npm. Versions are generated from a hash of the build's contents, e.g. 0.0.0-experimental-1022ee0ec.
What Goes Into an Experimental Release?
Experimental features are ones that are not ready to be released to the wider public, and may change drastically before they are finalized. Some experiments may never be finalized ¡ª the reason we have experiments is to test the viability of proposed changes. For example, if the Experimental channel had existed when we announced Hooks, we would have released Hooks to the Experimental channel weeks before they were available in Latest. You may find it valuable to run integration tests against Experimental. This is up to you. However, be advised that Experimental is even less stable than Next. We do not guarantee any stability between Experimental releases.
How Can I Learn More About Experimental Features?
Experimental features may or may not be documented. Usually, experiments aren't documented until they are close to shipping in Next or Latest. If a feature is not documented, they may be accompanied by an RFC. We will post to the React blog when we're ready to announce new experiments, but that doesn't mean we will publicize every experiment. You can always refer to our public GitHub repository's history for a comprehensive list of changes.

Hello World

The smallest React example looks like this: ReactDOM.render( <h2>Hello, world!</h2>, document.getElementById('root') ); It displays a heading saying ¡°Hello, world!¡± on the page. Try it on CodePen Click the link above to open an online editor. Feel free to make some changes, and see how they affect the output. Most pages in this guide will have editable examples like this one.

How to Read This Guide

In this guide, we will examine the building blocks of React apps: elements and components. Once you master them, you can create complex apps from small reusable pieces.
Tip This guide is designed for people who prefer learning concepts step by step. If you prefer to learn by doing, check out our practical tutorial. You might find this guide and the tutorial complementary to each other.
This is the first chapter in a step-by-step guide about main React concepts. You can find a list of all its chapters in the navigation sidebar. If you're reading this from a mobile device, you can access the navigation by pressing the button in the bottom right corner of your screen. Every chapter in this guide builds on the knowledge introduced in earlier chapters. You can learn most of React by reading the ¡°Main Concepts¡± guide chapters in the order they appear in the sidebar. For example, ¡°Introducing JSX¡± is the next chapter after this one.

Knowledge Level Assumptions

React is a JavaScript library, and so we'll assume you have a basic understanding of the JavaScript language. If you don't feel very confident, we recommend going through a JavaScript tutorial to check your knowledge level and enable you to follow along this guide without getting lost. It might take you between 30 minutes and an hour, but as a result you won't have to feel like you're learning both React and JavaScript at the same time.
Note This guide occasionally uses some of the newer JavaScript syntax in the examples. If you haven't worked with JavaScript in the last few years, these three points should get you most of the way.

Let's Get Started!

Keep scrolling down, and you'll find the link to the next chapter of this guide right before the website footer.

Introducing JSX

Consider this variable declaration: const element = <h2>Hello, world!</h2>; This funny tag syntax is neither a string nor HTML. It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript. JSX produces React ¡°elements¡±. We will explore rendering them to the DOM in the next section. Below, you can find the basics of JSX necessary to get you started.

Why JSX?

React embraces the fact that rendering logic is inherently coupled with other UI logic: how events are handled, how the state changes over time, and how the data is prepared for display. Instead of artificially separating technologies by putting markup and logic in separate files, React separates concerns with loosely coupled units called ¡°components¡± that contain both. We will come back to components in a further section, but if you're not yet comfortable putting markup in JS, this talk might convince you otherwise. React doesn't require using JSX, but most people find it helpful as a visual aid when working with UI inside the JavaScript code. It also allows React to show more useful error and warning messages. With that out of the way, let's get started!

Embedding Expressions in JSX

In the example below, we declare a variable called name and then use it inside JSX by wrapping it in curly braces: const name = 'Josh Perez';const element = <h2>Hello, {name}</h2>; ReactDOM.render( element, document.getElementById('root') ); You can put any valid JavaScript expression inside the curly braces in JSX. For example, 2 + 2, user.firstName, or formatName(user) are all valid JavaScript expressions. In the example below, we embed the result of calling a JavaScript function, formatName(user), into an <h2> element. function formatName(user) { return user.firstName + ' ' + user.lastName; } const user = { firstName: 'Harper', lastName: 'Perez' }; const element = ( <h2> Hello, {formatName(user)}! </h2> ); ReactDOM.render( element, document.getElementById('root') ); Try it on CodePen We split JSX over multiple lines for readability. While it isn't required, when doing this, we also recommend wrapping it in parentheses to avoid the pitfalls of automatic semicolon insertion.

JSX is an Expression Too

After compilation, JSX expressions become regular JavaScript function calls and evaluate to JavaScript objects. This means that you can use JSX inside of if statements and for loops, assign it to variables, accept it as arguments, and return it from functions: function getGreeting(user) { if (user) { return <h2>Hello, {formatName(user)}!</h2>; } return <h2>Hello, Stranger.</h2>;}

Specifying Attributes with JSX

You may use quotes to specify string literals as attributes: const element = <div tabIndex="0"></div>; You may also use curly braces to embed a JavaScript expression in an attribute: const element = <img src={user.avatarUrl}></img>; Don't put quotes around curly braces when embedding a JavaScript expression in an attribute. You should either use quotes (for string values) or curly braces (for expressions), but not both in the same attribute.
Warning: Since JSX is closer to JavaScript than to HTML, React DOM uses camelCase property naming convention instead of HTML attribute names. For example, class becomes className in JSX, and tabindex becomes tabIndex.

Specifying Children with JSX

If a tag is empty, you may close it immediately with />, like XML: const element = <img src={user.avatarUrl} />; JSX tags may contain children: const element = ( <div> <h2>Hello!</h2> <h3>Good to see you here.</h3> </div> );

JSX Prevents Injection Attacks

It is safe to embed user input in JSX: const title = response.potentiallyMaliciousInput; // This is safe: const element = <h2>{title}</h2>; By default, React DOM escapes any values embedded in JSX before rendering them. Thus it ensures that you can never inject anything that's not explicitly written in your application. Everything is converted to a string before being rendered. This helps prevent XSS (cross-site-scripting) attacks.

JSX Represents Objects

Babel compiles JSX down to React.createElement() calls. These two examples are identical: const element = ( <h2 className="greeting"> Hello, world! </h2> ); const element = React.createElement( 'h2', {className: 'greeting'}, 'Hello, world!' ); React.createElement() performs a few checks to help you write bug-free code but essentially it creates an object like this: // Note: this structure is simplified const element = { type: 'h2', props: { className: 'greeting', children: 'Hello, world!' } }; These objects are called ¡°React elements¡±. You can think of them as descriptions of what you want to see on the screen. React reads these objects and uses them to construct the DOM and keep it up to date. We will explore rendering React elements to the DOM in the next section.
Tip: We recommend using the ¡°Babel¡± language definition for your editor of choice so that both ES6 and JSX code is properly highlighted.

Rendering Elements

Elements are the smallest building blocks of React apps. An element describes what you want to see on the screen: const element = <h2>Hello, world</h2>; Unlike browser DOM elements, React elements are plain objects, and are cheap to create. React DOM takes care of updating the DOM to match the React elements.
Note: One might confuse elements with a more widely known concept of ¡°components¡±. We will introduce components in the next section. Elements are what components are ¡°made of¡±, and we encourage you to read this section before jumping ahead.

Rendering an Element into the DOM

Let's say there is a <div> somewhere in your HTML file: <div> We call this a ¡°root¡± DOM node because everything inside it will be managed by React DOM. Applications built with just React usually have a single root DOM node. If you are integrating React into an existing app, you may have as many isolated root DOM nodes as you like. To render a React element into a root DOM node, pass both to ReactDOM.render(): const element = <h2>Hello, world</h2>; ReactDOM.render(element, document.getElementById('root')); Try it on CodePen It displays ¡°Hello, world¡± on the page.

Updating the Rendered Element

React elements are immutable. Once you create an element, you can't change its children or attributes. An element is like a single frame in a movie: it represents the UI at a certain point in time. With our knowledge so far, the only way to update the UI is to create a new element, and pass it to ReactDOM.render(). Consider this ticking clock example: function tick() { const element = ( <div> <h2>Hello, world!</h2> <h3>It is {new Date().toLocaleTimeString()}.</h3> </div> ); ReactDOM.render(element, document.getElementById('root'));} setInterval(tick, 1000); Try it on CodePen It calls ReactDOM.render() every second from a setInterval() callback.
Note: In practice, most React apps only call ReactDOM.render() once. In the next sections we will learn how such code gets encapsulated into stateful components. We recommend that you don't skip topics because they build on each other.

React Only Updates What's Necessary

React DOM compares the element and its children to the previous one, and only applies the DOM updates necessary to bring the DOM to the desired state. You can verify by inspecting the last example with the browser tools: Even though we create an element describing the whole UI tree on every tick, only the text node whose contents have changed gets updated by React DOM. In our experience, thinking about how the UI should look at any given moment, rather than how to change it over time, eliminates a whole class of bugs.

Components and Props

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. This page provides an introduction to the idea of components. You can find a detailed component API reference here. Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called ¡°props¡±) and return React elements describing what should appear on the screen.

Function and Class Components

The simplest way to define a component is to write a JavaScript function: function Welcome(props) { return <h2>Hello, {props.name}</h2>; } This function is a valid React component because it accepts a single ¡°props¡± (which stands for properties) object argument with data and returns a React element. We call such components ¡°function components¡± because they are literally JavaScript functions. You can also use an ES6 class to define a component: class Welcome extends React.Component { render() { return <h2>Hello, {this.props.name}</h2>; } } The above two components are equivalent from React's point of view. Function and Class components both have some additional features that we will discuss in the next sections.

Rendering a Component

Previously, we only encountered React elements that represent DOM tags: const element = <div />; However, elements can also represent user-defined components: const element = <Welcome name="Sara" />; When React sees an element representing a user-defined component, it passes JSX attributes and children to this component as a single object. We call this object ¡°props¡±. For example, this code renders ¡°Hello, Sara¡± on the page: function Welcome(props) { return <h2>Hello, {props.name}</h2>; } const element = <Welcome name="Sara" />;ReactDOM.render( element, document.getElementById('root') ); Try it on CodePen Let's recap what happens in this example:
  1. We call ReactDOM.render() with the <Welcome name="Sara" /> element.
  2. React calls the Welcome component with {name: 'Sara'} as the props.
  3. Our Welcome component returns a <h2>Hello, Sara</h2> element as the result.
  4. React DOM efficiently updates the DOM to match <h2>Hello, Sara</h2>.
Note: Always start component names with a capital letter. React treats components starting with lowercase letters as DOM tags. For example, <div /> represents an HTML div tag, but <Welcome /> represents a component and requires Welcome to be in scope. To learn more about the reasoning behind this convention, please read JSX In Depth.

Composing Components

Components can refer to other components in their output. This lets us use the same component abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components. For example, we can create an App component that renders Welcome many times: function Welcome(props) { return <h2>Hello, {props.name}</h2>; } function App() { return ( <div> <Welcome name="Sara" /> <Welcome name="Cahal" /> <Welcome name="Edite" /> </div> ); } ReactDOM.render( <App />, document.getElementById('root') ); Try it on CodePen Typically, new React apps have a single App component at the very top. However, if you integrate React into an existing app, you might start bottom-up with a small component like Button and gradually work your way to the top of the view hierarchy.

Extracting Components

Don't be afraid to split components into smaller components. For example, consider this Comment component: function Comment(props) { return ( <div className="Comment"> <div className="UserInfo"> <img className="Avatar" src={props.author.avatarUrl} alt={props.author.name} /> <div className="UserInfo-name"> {props.author.name} </div> </div> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formatDate(props.date)} </div> </div> ); } Try it on CodePen It accepts author (an object), text (a string), and date (a date) as props, and describes a comment on a social media website. This component can be tricky to change because of all the nesting, and it is also hard to reuse individual parts of it. Let's extract a few components from it. First, we will extract Avatar: function Avatar(props) { return ( <img className="Avatar" src={props.user.avatarUrl} alt={props.user.name} /> ); } The Avatar doesn't need to know that it is being rendered inside a Comment. This is why we have given its prop a more generic name: user rather than author. We recommend naming props from the component's own point of view rather than the context in which it is being used. We can now simplify Comment a tiny bit: function Comment(props) { return ( <div className="Comment"> <div className="UserInfo"> <Avatar user={props.author} /> <div className="UserInfo-name"> {props.author.name} </div> </div> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formatDate(props.date)} </div> </div> ); } Next, we will extract a UserInfo component that renders an Avatar next to the user's name: function UserInfo(props) { return ( <div className="UserInfo"> <Avatar user={props.user} /> <div className="UserInfo-name"> {props.user.name} </div> </div> ); } This lets us simplify Comment even further: function Comment(props) { return ( <div className="Comment"> <UserInfo user={props.author} /> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formatDate(props.date)} </div> </div> ); } Try it on CodePen Extracting components might seem like grunt work at first, but having a palette of reusable components pays off in larger apps. A good rule of thumb is that if a part of your UI is used several times (Button, Panel, Avatar), or is complex enough on its own (App, FeedStory, Comment), it is a good candidate to be extracted to a separate component.

Props are Read-Only

Whether you declare a component as a function or a class, it must never modify its own props. Consider this sum function: function sum(a, b) { return a + b; } Such functions are called ¡°pure¡± because they do not attempt to change their inputs, and always return the same result for the same inputs. In contrast, this function is impure because it changes its own input: function withdraw(account, amount) { account.total -= amount; } React is pretty flexible but it has a single strict rule: All React components must act like pure functions with respect to their props. Of course, application UIs are dynamic and change over time. In the next section, we will introduce a new concept of ¡°state¡±. State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.

State and Lifecycle

This page introduces the concept of state and lifecycle in a React component. You can find a detailed component API reference here. Consider the ticking clock example from one of the previous sections. In Rendering Elements, we have only learned one way to update the UI. We call ReactDOM.render() to change the rendered output: function tick() { const element = ( <div> <h2>Hello, world!</h2> <h3>It is {new Date().toLocaleTimeString()}.</h3> </div> ); ReactDOM.render( element, document.getElementById('root') );} setInterval(tick, 1000); Try it on CodePen In this section, we will learn how to make the Clock component truly reusable and encapsulated. It will set up its own timer and update itself every second. We can start by encapsulating how the clock looks: function Clock(props) { return ( <div> <h2>Hello, world!</h2> <h3>It is {props.date.toLocaleTimeString()}.</h3> </div> ); } function tick() { ReactDOM.render( <Clock date={new Date()} />, document.getElementById('root') ); } setInterval(tick, 1000); Try it on CodePen However, it misses a crucial requirement: the fact that the Clock sets up a timer and updates the UI every second should be an implementation detail of the Clock. Ideally we want to write this once and have the Clock update itself: ReactDOM.render( <Clock />, document.getElementById('root') ); To implement this, we need to add ¡°state¡± to the Clock component. State is similar to props, but it is private and fully controlled by the component.

Converting a Function to a Class

You can convert a function component like Clock to a class in five steps:
  1. Create an ES6 class, with the same name, that extends React.Component.
  2. Add a single empty method to it called render().
  3. Move the body of the function into the render() method.
  4. Replace props with this.props in the render() body.
  5. Delete the remaining empty function declaration.
class Clock extends React.Component { render() { return ( <div> <h2>Hello, world!</h2> <h3>It is {this.props.date.toLocaleTimeString()}.</h3> </div> ); } } Try it on CodePen Clock is now defined as a class rather than a function. The render method will be called each time an update happens, but as long as we render <Clock /> into the same DOM node, only a single instance of the Clock class will be used. This lets us use additional features such as local state and lifecycle methods.

Adding Local State to a Class

We will move the date from props to state in three steps:
  1. Replace this.props.date with this.state.date in the render() method:
class Clock extends React.Component { render() { return ( <div> <h2>Hello, world!</h2> <h3>It is {this.state.date.toLocaleTimeString()}.</h3> </div> ); } }
  1. Add a class constructor that assigns the initial this.state:
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h2>Hello, world!</h2> <h3>It is {this.state.date.toLocaleTimeString()}.</h3> </div> ); } } Note how we pass props to the base constructor: constructor(props) { super(props); this.state = {date: new Date()}; } Class components should always call the base constructor with props.
  1. Remove the date prop from the <Clock /> element:
ReactDOM.render( <Clock />, document.getElementById('root') ); We will later add the timer code back to the component itself. The result looks like this: class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h2>Hello, world!</h2> <h3>It is {this.state.date.toLocaleTimeString()}.</h3> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') ); Try it on CodePen Next, we'll make the Clock set up its own timer and update itself every second.

Adding Lifecycle Methods to a Class

In applications with many components, it's very important to free up resources taken by the components when they are destroyed. We want to set up a timer whenever the Clock is rendered to the DOM for the first time. This is called ¡°mounting¡± in React. We also want to clear that timer whenever the DOM produced by the Clock is removed. This is called ¡°unmounting¡± in React. We can declare special methods on the component class to run some code when a component mounts and unmounts: class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { } componentWillUnmount() { } render() { return ( <div> <h2>Hello, world!</h2> <h3>It is {this.state.date.toLocaleTimeString()}.</h3> </div> ); } } These methods are called ¡°lifecycle methods¡±. The componentDidMount() method runs after the component output has been rendered to the DOM. This is a good place to set up a timer: componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } Note how we save the timer ID right on this (this.timerID). While this.props is set up by React itself and this.state has a special meaning, you are free to add additional fields to the class manually if you need to store something that doesn't participate in the data flow (like a timer ID). We will tear down the timer in the componentWillUnmount() lifecycle method: componentWillUnmount() { clearInterval(this.timerID); } Finally, we will implement a method called tick() that the Clock component will run every second. It will use this.setState() to schedule updates to the component local state: class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return ( <div> <h2>Hello, world!</h2> <h3>It is {this.state.date.toLocaleTimeString()}.</h3> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') ); Try it on CodePen Now the clock ticks every second. Let's quickly recap what's going on and the order in which the methods are called:
  1. When <Clock /> is passed to ReactDOM.render(), React calls the constructor of the Clock component. Since Clock needs to display the current time, it initializes this.state with an object including the current time. We will later update this state.
  2. React then calls the Clock component's render() method. This is how React learns what should be displayed on the screen. React then updates the DOM to match the Clock's render output.
  3. When the Clock output is inserted in the DOM, React calls the componentDidMount() lifecycle method. Inside it, the Clock component asks the browser to set up a timer to call the component's tick() method once a second.
  4. Every second the browser calls the tick() method. Inside it, the Clock component schedules a UI update by calling setState() with an object containing the current time. Thanks to the setState() call, React knows the state has changed, and calls the render() method again to learn what should be on the screen. This time, this.state.date in the render() method will be different, and so the render output will include the updated time. React updates the DOM accordingly.
  5. If the Clock component is ever removed from the DOM, React calls the componentWillUnmount() lifecycle method so the timer is stopped.

Using State Correctly

There are three things you should know about setState().

Do Not Modify State Directly

For example, this will not re-render a component: // Wrong this.state.comment = 'Hello'; Instead, use setState(): // Correct this.setState({comment: 'Hello'}); The only place where you can assign this.state is the constructor.

State Updates May Be Asynchronous

React may batch multiple setState() calls into a single update for performance. Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state. For example, this code may fail to update the counter: // Wrong this.setState({ counter: this.state.counter + this.props.increment, }); To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument: // Correct this.setState((state, props) => ({ counter: state.counter + props.increment })); We used an arrow function above, but it also works with regular functions: // Correct this.setState(function(state, props) { return { counter: state.counter + props.increment }; });

State Updates are Merged

When you call setState(), React merges the object you provide into the current state. For example, your state may contain several independent variables: constructor(props) { super(props); this.state = { posts: [], comments: [] }; } Then you can update them independently with separate setState() calls: componentDidMount() { fetchPosts().then(response => { this.setState({ posts: response.posts }); }); fetchComments().then(response => { this.setState({ comments: response.comments }); }); } The merging is shallow, so this.setState({comments}) leaves this.state.posts intact, but completely replaces this.state.comments.

The Data Flows Down

Neither parent nor child components can know if a certain component is stateful or stateless, and they shouldn't care whether it is defined as a function or a class. This is why state is often called local or encapsulated. It is not accessible to any component other than the one that owns and sets it. A component may choose to pass its state down as props to its child components: <FormattedDate date={this.state.date} /> The FormattedDate component would receive the date in its props and wouldn't know whether it came from the Clock's state, from the Clock's props, or was typed by hand: function FormattedDate(props) { return <h3>It is {props.date.toLocaleTimeString()}.</h3>; } Try it on CodePen This is commonly called a ¡°top-down¡± or ¡°unidirectional¡± data flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components ¡°below¡± them in the tree. If you imagine a component tree as a waterfall of props, each component's state is like an additional water source that joins it at an arbitrary point but also flows down. To show that all components are truly isolated, we can create an App component that renders three <Clock>s: function App() { return ( <div> <Clock /> <Clock /> <Clock /> </div> ); } ReactDOM.render( <App />, document.getElementById('root') ); Try it on CodePen Each Clock sets up its own timer and updates independently. In React apps, whether a component is stateful or stateless is considered an implementation detail of the component that may change over time. You can use stateless components inside stateful components, and vice versa.

Handling Events

Handling events with React elements is very similar to handling events on DOM elements. There are some syntax differences: For example, the HTML: <button onclick="activateLasers()"> Activate Lasers </button> is slightly different in React: <button onClick={activateLasers}> Activate Lasers </button> Another difference is that you cannot return false to prevent default behavior in React. You must call preventDefault explicitly. For example, with plain HTML, to prevent the default link behavior of opening a new page, you can write: <a href="#" onclick="console.log('The link was clicked.'); return false"> Click me </a> In React, this could instead be: function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('The link was clicked.'); } return ( <a href="#" onClick={handleClick}> Click me </a> ); } Here, e is a synthetic event. React defines these synthetic events according to the W3C spec, so you don't need to worry about cross-browser compatibility. React events do not work exactly the same as native events. See the SyntheticEvent reference guide to learn more. When using React, you generally don't need to call addEventListener to add listeners to a DOM element after it is created. Instead, just provide a listener when the element is initially rendered. When you define a component using an ES6 class, a common pattern is for an event handler to be a method on the class. For example, this Toggle component renders a button that lets the user toggle between ¡°ON¡± and ¡°OFF¡± states: class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // This binding is necessary to make `this` work in the callback this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(state => ({ isToggleOn: !state.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); } } ReactDOM.render( <Toggle />, document.getElementById('root') ); Try it on CodePen You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called. This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method. If calling bind annoys you, there are two ways you can get around this. If you are using the experimental public class fields syntax, you can use class fields to correctly bind callbacks: class LoggingButton extends React.Component { // This syntax ensures `this` is bound within handleClick. // Warning: this is *experimental* syntax. handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } } This syntax is enabled by default in Create React App. If you aren't using class fields syntax, you can use an arrow function in the callback: class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { // This syntax ensures `this` is bound within handleClick return ( <button onClick={() => this.handleClick()}> Click me </button> ); } } The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.

Passing Arguments to Event Handlers

Inside a loop, it is common to want to pass an extra parameter to an event handler. For example, if id is the row ID, either of the following would work: <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button> The above two lines are equivalent, and use arrow functions and Function.prototype.bind respectively. In both cases, the e argument representing the React event will be passed as a second argument after the ID. With an arrow function, we have to pass it explicitly, but with bind any further arguments are automatically forwarded.

Conditional Rendering

In React, you can create distinct components that encapsulate behavior you need. Then, you can render only some of them, depending on the state of your application. Conditional rendering in React works the same way conditions work in JavaScript. Use JavaScript operators like if or the conditional operator to create elements representing the current state, and let React update the UI to match them. Consider these two components: function UserGreeting(props) { return <h2>Welcome back!</h2>; } function GuestGreeting(props) { return <h2>Please sign up.</h2>; } We'll create a Greeting component that displays either of these components depending on whether a user is logged in: function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />;} ReactDOM.render( // Try changing to isLoggedIn={true}: <Greeting isLoggedIn={false} />, document.getElementById('root')); Try it on CodePen This example renders a different greeting depending on the value of isLoggedIn prop.

Element Variables

You can use variables to store elements. This can help you conditionally render a part of the component while the rest of the output doesn't change. Consider these two new components representing Logout and Login buttons: function LoginButton(props) { return ( <button onClick={props.onClick}> Login </button> ); } function LogoutButton(props) { return ( <button onClick={props.onClick}> Logout </button> ); } In the example below, we will create a stateful component called LoginControl. It will render either <LoginButton /> or <LogoutButton /> depending on its current state. It will also render a <Greeting /> from the previous example: class LoginControl extends React.Component { constructor(props) { super(props); this.handleLoginClick = this.handleLoginClick.bind(this); this.handleLogoutClick = this.handleLogoutClick.bind(this); this.state = {isLoggedIn: false}; } handleLoginClick() { this.setState({isLoggedIn: true}); } handleLogoutClick() { this.setState({isLoggedIn: false}); } render() { const isLoggedIn = this.state.isLoggedIn; let button; if (isLoggedIn) { button = <LogoutButton onClick={this.handleLogoutClick} />; } else { button = <LoginButton onClick={this.handleLoginClick} />; } return ( <div> <Greeting isLoggedIn={isLoggedIn} /> {button} </div> ); } } ReactDOM.render( <LoginControl />, document.getElementById('root') ); Try it on CodePen While declaring a variable and using an if statement is a fine way to conditionally render a component, sometimes you might want to use a shorter syntax. There are a few ways to inline conditions in JSX, explained below.

Inline If with Logical && Operator

You may embed expressions in JSX by wrapping them in curly braces. This includes the JavaScript logical && operator. It can be handy for conditionally including an element: function Mailbox(props) { const unreadMessages = props.unreadMessages; return ( <div> <h2>Hello!</h2> {unreadMessages.length > 0 && <h3> You have {unreadMessages.length} unread messages. </h3> } </div> ); } const messages = ['React', 'Re: React', 'Re:Re: React']; ReactDOM.render( <Mailbox unreadMessages={messages} />, document.getElementById('root') ); Try it on CodePen It works because in JavaScript, true && expression always evaluates to expression, and false && expression always evaluates to false. Therefore, if the condition is true, the element right after && will appear in the output. If it is false, React will ignore and skip it. Note that returning a falsy expression will still cause the element after && to be skipped but will return the falsy expression. In the example below, <div>0</div> will be returned by the render method. render() { const count = 0; return ( <div> { count && <h2>Messages: {count}</h2>} </div> ); }

Inline If-Else with Conditional Operator

Another method for conditionally rendering elements inline is to use the JavaScript conditional operator condition ? true : false. In the example below, we use it to conditionally render a small block of text. render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in. </div> ); } It can also be used for larger expressions although it is less obvious what's going on: render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> {isLoggedIn ? <LogoutButton onClick={this.handleLogoutClick} /> : <LoginButton onClick={this.handleLoginClick} /> } </div> ); } Just like in JavaScript, it is up to you to choose an appropriate style based on what you and your team consider more readable. Also remember that whenever conditions become too complex, it might be a good time to extract a component.

Preventing Component from Rendering

In rare cases you might want a component to hide itself even though it was rendered by another component. To do this return null instead of its render output. In the example below, the <WarningBanner /> is rendered depending on the value of the prop called warn. If the value of the prop is false, then the component does not render: function WarningBanner(props) { if (!props.warn) { return null; } return ( <div className="warning"> Warning! </div> ); } class Page extends React.Component { constructor(props) { super(props); this.state = {showWarning: true}; this.handleToggleClick = this.handleToggleClick.bind(this); } handleToggleClick() { this.setState(state => ({ showWarning: !state.showWarning })); } render() { return ( <div> <WarningBanner warn={this.state.showWarning} /> <button onClick={this.handleToggleClick}> {this.state.showWarning ? 'Hide' : 'Show'} </button> </div> ); } } ReactDOM.render( <Page />, document.getElementById('root') ); Try it on CodePen Returning null from a component's render method does not affect the firing of the component's lifecycle methods. For instance componentDidUpdate will still be called.

Lists and Keys

First, let's review how you transform lists in JavaScript. Given the code below, we use the map() function to take an array of numbers and double their values. We assign the new array returned by map() to the variable doubled and log it: const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map((number) => number * 2);console.log(doubled); This code logs [2, 4, 6, 8, 10] to the console. In React, transforming arrays into lists of elements is nearly identical.

Rendering Multiple Components

You can build collections of elements and include them in JSX using curly braces {}. Below, we loop through the numbers array using the JavaScript map() function. We return a <li> element for each item. Finally, we assign the resulting array of elements to listItems: const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li>{number}</li>); We include the entire listItems array inside a <ul> element, and render it to the DOM: ReactDOM.render( <ul>{listItems}</ul>, document.getElementById('root') ); Try it on CodePen This code displays a bullet list of numbers between 1 and 5.

Basic List Component

Usually you would render lists inside a component. We can refactor the previous example into a component that accepts an array of numbers and outputs a list of elements. function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li>{number}</li> ); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); When you run this code, you'll be given a warning that a key should be provided for list items. A ¡°key¡± is a special string attribute you need to include when creating lists of elements. We'll discuss why it's important in the next section. Let's assign a key to our list items inside numbers.map() and fix the missing key issue. function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); Try it on CodePen

Keys

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity: const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys: const todoItems = todos.map((todo) => <li key={todo.id}> {todo.text} </li> ); When you don't have stable IDs for rendered items, you may use the item index as a key as a last resort: const todoItems = todos.map((todo, index) => // Only do this if items have no stable IDs <li key={index}> {todo.text} </li> ); We don't recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state. Check out Robin Pokorny's article for an in-depth explanation on the negative impacts of using an index as a key. If you choose not to assign an explicit key to list items then React will default to using indexes as keys. Here is an in-depth explanation about why keys are necessary if you're interested in learning more.

Extracting Components with Keys

Keys only make sense in the context of the surrounding array. For example, if you extract a ListItem component, you should keep the key on the <ListItem /> elements in the array rather than on the <li> element in the ListItem itself. Example: Incorrect Key Usage function ListItem(props) { const value = props.value; return ( // Wrong! There is no need to specify the key here: <li key={value.toString()}> {value} </li> ); } function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // Wrong! The key should have been specified here: <ListItem value={number} /> ); return ( <ul> {listItems} </ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); Example: Correct Key Usage function ListItem(props) { // Correct! There is no need to specify the key here: return <li>{props.value}</li>;} function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // Correct! Key should be specified inside the array. <ListItem key={number.toString()} value={number} /> ); return ( <ul> {listItems} </ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); Try it on CodePen A good rule of thumb is that elements inside the map() call need keys.

Keys Must Only Be Unique Among Siblings

Keys used within arrays should be unique among their siblings. However they don't need to be globally unique. We can use the same keys when we produce two different arrays: function Blog(props) { const sidebar = ( <ul> {props.posts.map((post) => <li key={post.id}> {post.title} </li> )} </ul> ); const content = props.posts.map((post) => <div key={post.id}> <h4>{post.title}</h4> <p>{post.content}</p> </div> ); return ( <div> {sidebar} <hr /> {content} </div> ); } const posts = [ {id: 1, title: 'Hello World', content: 'Welcome to learning React!'}, {id: 2, title: 'Installation', content: 'You can install React from npm.'} ]; ReactDOM.render( <Blog posts={posts} />, document.getElementById('root') ); Try it on CodePen Keys serve as a hint to React but they don't get passed to your components. If you need the same value in your component, pass it explicitly as a prop with a different name: const content = posts.map((post) => <Post key={post.id} id={post.id} title={post.title} /> ); With the example above, the Post component can read props.id, but not props.key.

Embedding map() in JSX

In the examples above we declared a separate listItems variable and included it in JSX: function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <ListItem key={number.toString()} value={number} /> ); return ( <ul> {listItems} </ul> ); } JSX allows embedding any expression in curly braces so we could inline the map() result: function NumberList(props) { const numbers = props.numbers; return ( <ul> {numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul> ); } Try it on CodePen Sometimes this results in clearer code, but this style can also be abused. Like in JavaScript, it is up to you to decide whether it is worth extracting a variable for readability. Keep in mind that if the map() body is too nested, it might be a good time to extract a component.

Forms

HTML form elements work a little bit differently from other DOM elements in React, because form elements naturally keep some internal state. For example, this form in plain HTML accepts a single name: <form> <label> Name: <input type="text" name="name" /> </label> <input type="submit" value="Submit" /> </form> This form has the default HTML form behavior of browsing to a new page when the user submits the form. If you want this behavior in React, it just works. But in most cases, it's convenient to have a JavaScript function that handles the submission of the form and has access to the data that the user entered into the form. The standard way to achieve this is with a technique called ¡°controlled components¡±.

Controlled Components

In HTML, form elements such as <input>, <textarea>, and <select> typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated with setState(). We can combine the two by making the React state be the ¡°single source of truth¡±. Then the React component that renders a form also controls what happens in that form on subsequent user input. An input form element whose value is controlled by React in this way is called a ¡°controlled component¡±. For example, if we want to make the previous example log the name when it is submitted, we can write the form as a controlled component: class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } Try it on CodePen Since the value attribute is set on our form element, the displayed value will always be this.state.value, making the React state the source of truth. Since handleChange runs on every keystroke to update the React state, the displayed value will update as the user types. With a controlled component, the input's value is always driven by the React state. While this means you have to type a bit more code, you can now pass the value to other UI elements too, or reset it from other event handlers.

The textarea Tag

In HTML, a <textarea> element defines its text by its children: <textarea> Hello there, this is some text in a text area </textarea> In React, a <textarea> uses a value attribute instead. This way, a form using a <textarea> can be written very similarly to a form that uses a single-line input: class EssayForm extends React.Component { constructor(props) { super(props); this.state = { value: 'Please write an essay about your favorite DOM element.' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('An essay was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Essay: <textarea value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } Notice that this.state.value is initialized in the constructor, so that the text area starts off with some text in it.

The select Tag

In HTML, <select> creates a drop-down list. For example, this HTML creates a drop-down list of flavors: <select> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option selected value="coconut">Coconut</option> <option value="mango">Mango</option> </select> Note that the Coconut option is initially selected, because of the selected attribute. React, instead of using this selected attribute, uses a value attribute on the root select tag. This is more convenient in a controlled component because you only need to update it in one place. For example: class FlavorForm extends React.Component { constructor(props) { super(props); this.state = {value: 'coconut'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('Your favorite flavor is: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Pick your favorite flavor: <select value={this.state.value} onChange={this.handleChange}> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </label> <input type="submit" value="Submit" /> </form> ); } } Try it on CodePen Overall, this makes it so that <input type="text">, <textarea>, and <select> all work very similarly - they all accept a value attribute that you can use to implement a controlled component.
Note You can pass an array into the value attribute, allowing you to select multiple options in a select tag: <select multiple={true} value={['B', 'C']}>

The file input Tag

In HTML, an <input type="file"> lets the user choose one or more files from their device storage to be uploaded to a server or manipulated by JavaScript via the File API. <input type="file" /> Because its value is read-only, it is an uncontrolled component in React. It is discussed together with other uncontrolled components later in the documentation.

Handling Multiple Inputs

When you need to handle multiple controlled input elements, you can add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name. For example: class Reservation extends React.Component { constructor(props) { super(props); this.state = { isGoing: true, numberOfGuests: 2 }; this.handleInputChange = this.handleInputChange.bind(this); } handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({ [name]: value }); } render() { return ( <form> <label> Is going: <input name="isGoing" type="checkbox" checked={this.state.isGoing} onChange={this.handleInputChange} /> </label> <br /> <label> Number of guests: <input name="numberOfGuests" type="number" value={this.state.numberOfGuests} onChange={this.handleInputChange} /> </label> </form> ); } } Try it on CodePen Note how we used the ES6 computed property name syntax to update the state key corresponding to the given input name: this.setState({ [name]: value}); It is equivalent to this ES5 code: var partialState = {}; partialState[name] = value;this.setState(partialState); Also, since setState() automatically merges a partial state into the current state, we only needed to call it with the changed parts.

Controlled Input Null Value

Specifying the value prop on a controlled component prevents the user from changing the input unless you desire so. If you've specified a value but the input is still editable, you may have accidentally set value to undefined or null. The following code demonstrates this. (The input is locked at first but becomes editable after a short delay.) ReactDOM.render(<input value="hi" />, mountNode); setTimeout(function() { ReactDOM.render(<input value={null} />, mountNode); }, 1000);

Alternatives to Controlled Components

It can sometimes be tedious to use controlled components, because you need to write an event handler for every way your data can change and pipe all of the input state through a React component. This can become particularly annoying when you are converting a preexisting codebase to React, or integrating a React application with a non-React library. In these situations, you might want to check out uncontrolled components, an alternative technique for implementing input forms.

Fully-Fledged Solutions

If you're looking for a complete solution including validation, keeping track of the visited fields, and handling form submission, Formik is one of the popular choices. However, it is built on the same principles of controlled components and managing state ¡ª so don't neglect to learn them.

Lifting State Up

Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor. Let's see how this works in action. In this section, we will create a temperature calculator that calculates whether the water would boil at a given temperature. We will start with a component called BoilingVerdict. It accepts the celsius temperature as a prop, and prints whether it is enough to boil the water: function BoilingVerdict(props) { if (props.celsius >= 100) { return <p>The water would boil.</p>; } return <p>The water would not boil.</p>;} Next, we will create a component called Calculator. It renders an <input> that lets you enter the temperature, and keeps its value in this.state.temperature. Additionally, it renders the BoilingVerdict for the current input value. class Calculator extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {temperature: ''}; } handleChange(e) { this.setState({temperature: e.target.value}); } render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> <BoilingVerdict celsius={parseFloat(temperature)} /> </fieldset> ); } } Try it on CodePen

Adding a Second Input

Our new requirement is that, in addition to a Celsius input, we provide a Fahrenheit input, and they are kept in sync. We can start by extracting a TemperatureInput component from Calculator. We will add a new scale prop to it that can either be "c" or "f": const scaleNames = { c: 'Celsius', f: 'Fahrenheit'}; class TemperatureInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {temperature: ''}; } handleChange(e) { this.setState({temperature: e.target.value}); } render() { const temperature = this.state.temperature; const scale = this.props.scale; return ( <fieldset> <legend>Enter temperature in {scaleNames[scale]}:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } We can now change the Calculator to render two separate temperature inputs: class Calculator extends React.Component { render() { return ( <div> <TemperatureInput scale="c" /> <TemperatureInput scale="f" /> </div> ); } } Try it on CodePen We have two inputs now, but when you enter the temperature in one of them, the other doesn't update. This contradicts our requirement: we want to keep them in sync. We also can't display the BoilingVerdict from Calculator. The Calculator doesn't know the current temperature because it is hidden inside the TemperatureInput.

Writing Conversion Functions

First, we will write two functions to convert from Celsius to Fahrenheit and back: function toCelsius(fahrenheit) { return (fahrenheit - 32) * 5 / 9; } function toFahrenheit(celsius) { return (celsius * 9 / 5) + 32; } These two functions convert numbers. We will write another function that takes a string temperature and a converter function as arguments and returns a string. We will use it to calculate the value of one input based on the other input. It returns an empty string on an invalid temperature, and it keeps the output rounded to the third decimal place: function tryConvert(temperature, convert) { const input = parseFloat(temperature); if (Number.isNaN(input)) { return ''; } const output = convert(input); const rounded = Math.round(output * 1000) / 1000; return rounded.toString(); } For example, tryConvert('abc', toCelsius) returns an empty string, and tryConvert('10.22', toFahrenheit) returns '50.396'.

Lifting State Up

Currently, both TemperatureInput components independently keep their values in the local state: class TemperatureInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {temperature: ''}; } handleChange(e) { this.setState({temperature: e.target.value}); } render() { const temperature = this.state.temperature; // ... However, we want these two inputs to be in sync with each other. When we update the Celsius input, the Fahrenheit input should reflect the converted temperature, and vice versa. In React, sharing state is accomplished by moving it up to the closest common ancestor of the components that need it. This is called ¡°lifting state up¡±. We will remove the local state from the TemperatureInput and move it into the Calculator instead. If the Calculator owns the shared state, it becomes the ¡°source of truth¡± for the current temperature in both inputs. It can instruct them both to have values that are consistent with each other. Since the props of both TemperatureInput components are coming from the same parent Calculator component, the two inputs will always be in sync. Let's see how this works step by step. First, we will replace this.state.temperature with this.props.temperature in the TemperatureInput component. For now, let's pretend this.props.temperature already exists, although we will need to pass it from the Calculator in the future: render() { // Before: const temperature = this.state.temperature; const temperature = this.props.temperature; // ... We know that props are read-only. When the temperature was in the local state, the TemperatureInput could just call this.setState() to change it. However, now that the temperature is coming from the parent as a prop, the TemperatureInput has no control over it. In React, this is usually solved by making a component ¡°controlled¡±. Just like the DOM <input> accepts both a value and an onChange prop, so can the custom TemperatureInput accept both temperature and onTemperatureChange props from its parent Calculator. Now, when the TemperatureInput wants to update its temperature, it calls this.props.onTemperatureChange: handleChange(e) { // Before: this.setState({temperature: e.target.value}); this.props.onTemperatureChange(e.target.value); // ...
Note: There is no special meaning to either temperature or onTemperatureChange prop names in custom components. We could have called them anything else, like name them value and onChange which is a common convention.
The onTemperatureChange prop will be provided together with the temperature prop by the parent Calculator component. It will handle the change by modifying its own local state, thus re-rendering both inputs with the new values. We will look at the new Calculator implementation very soon. Before diving into the changes in the Calculator, let's recap our changes to the TemperatureInput component. We have removed the local state from it, and instead of reading this.state.temperature, we now read this.props.temperature. Instead of calling this.setState() when we want to make a change, we now call this.props.onTemperatureChange(), which will be provided by the Calculator: class TemperatureInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } handleChange(e) { this.props.onTemperatureChange(e.target.value); } render() { const temperature = this.props.temperature; const scale = this.props.scale; return ( <fieldset> <legend>Enter temperature in {scaleNames[scale]}:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } Now let's turn to the Calculator component. We will store the current input's temperature and scale in its local state. This is the state we ¡°lifted up¡± from the inputs, and it will serve as the ¡°source of truth¡± for both of them. It is the minimal representation of all the data we need to know in order to render both inputs. For example, if we enter 37 into the Celsius input, the state of the Calculator component will be: { temperature: '37', scale: 'c' } If we later edit the Fahrenheit field to be 212, the state of the Calculator will be: { temperature: '212', scale: 'f' } We could have stored the value of both inputs but it turns out to be unnecessary. It is enough to store the value of the most recently changed input, and the scale that it represents. We can then infer the value of the other input based on the current temperature and scale alone. The inputs stay in sync because their values are computed from the same state: class Calculator extends React.Component { constructor(props) { super(props); this.handleCelsiusChange = this.handleCelsiusChange.bind(this); this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this); this.state = {temperature: '', scale: 'c'}; } handleCelsiusChange(temperature) { this.setState({scale: 'c', temperature}); } handleFahrenheitChange(temperature) { this.setState({scale: 'f', temperature}); } render() { const scale = this.state.scale; const temperature = this.state.temperature; const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature; const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature; return ( <div> <TemperatureInput scale="c" temperature={celsius} onTemperatureChange={this.handleCelsiusChange} /> <TemperatureInput scale="f" temperature={fahrenheit} onTemperatureChange={this.handleFahrenheitChange} /> <BoilingVerdict celsius={parseFloat(celsius)} /> </div> ); } } Try it on CodePen Now, no matter which input you edit, this.state.temperature and this.state.scale in the Calculator get updated. One of the inputs gets the value as is, so any user input is preserved, and the other input value is always recalculated based on it. Let's recap what happens when you edit an input: Every update goes through the same steps so the inputs stay in sync.

Lessons Learned

There should be a single ¡°source of truth¡± for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the top-down data flow. Lifting state involves writing more ¡°boilerplate¡± code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs. Since any state ¡°lives¡± in some component and that component alone can change it, the surface area for bugs is greatly reduced. Additionally, you can implement any custom logic to reject or transform user input. If something can be derived from either props or state, it probably shouldn't be in the state. For example, instead of storing both celsiusValue and fahrenheitValue, we store just the last edited temperature and its scale. The value of the other input can always be calculated from them in the render() method. This lets us clear or apply rounding to the other field without losing any precision in the user input. When you see something wrong in the UI, you can use React Developer Tools to inspect the props and move up the tree until you find the component responsible for updating the state. This lets you trace the bugs to their source:

Composition vs Inheritance

React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components. In this section, we will consider a few problems where developers new to React often reach for inheritance, and show how we can solve them with composition.

Containment

Some components don't know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic ¡°boxes¡±. We recommend that such components use the special children prop to pass children elements directly into their output: function FancyBorder(props) { return ( <div className={'FancyBorder FancyBorder-' + props.color}> {props.children} </div> ); } This lets other components pass arbitrary children to them by nesting the JSX: function WelcomeDialog() { return ( <FancyBorder color="blue"> <h2 className="Dialog-title"> Welcome </h2> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder> ); } Try it on CodePen Anything inside the <FancyBorder> JSX tag gets passed into the FancyBorder component as a children prop. Since FancyBorder renders {props.children} inside a <div>, the passed elements appear in the final output. While this is less common, sometimes you might need multiple ¡°holes¡± in a component. In such cases you may come up with your own convention instead of using children: function SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); } function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); } Try it on CodePen React elements like <Contacts /> and <Chat /> are just objects, so you can pass them as props like any other data. This approach may remind you of ¡°slots¡± in other libraries but there are no limitations on what you can pass as props in React.

Specialization

Sometimes we think about components as being ¡°special cases¡± of other components. For example, we might say that a WelcomeDialog is a special case of Dialog. In React, this is also achieved by composition, where a more ¡°specific¡± component renders a more ¡°generic¡± one and configures it with props: function Dialog(props) { return ( <FancyBorder color="blue"> <h2 className="Dialog-title"> {props.title} </h2> <p className="Dialog-message"> {props.message} </p> </FancyBorder> ); } function WelcomeDialog() { return ( <Dialog title="Welcome" message="Thank you for visiting our spacecraft!" /> ); } Try it on CodePen Composition works equally well for components defined as classes: function Dialog(props) { return ( <FancyBorder color="blue"> <h2 className="Dialog-title"> {props.title} </h2> <p className="Dialog-message"> {props.message} </p> {props.children} </FancyBorder> ); } class SignUpDialog extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.handleSignUp = this.handleSignUp.bind(this); this.state = {login: ''}; } render() { return ( <Dialog title="Mars Exploration Program" message="How should we refer to you?"> <input value={this.state.login} onChange={this.handleChange} /> <button onClick={this.handleSignUp}> Sign Me Up! </button> </Dialog> ); } handleChange(e) { this.setState({login: e.target.value}); } handleSignUp() { alert(`Welcome aboard, ${this.state.login}!`); } } Try it on CodePen

So What About Inheritance?

At Facebook, we use React in thousands of components, and we haven't found any use cases where we would recommend creating component inheritance hierarchies. Props and composition give you all the flexibility you need to customize a component's look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions. If you want to reuse non-UI functionality between components, we suggest extracting it into a separate JavaScript module. The components may import it and use that function, object, or a class, without extending it.

Thinking in React

React is, in our opinion, the premier way to build big, fast Web apps with JavaScript. It has scaled very well for us at Facebook and Instagram. One of the many great parts of React is how it makes you think about apps as you build them. In this document, we'll walk you through the thought process of building a searchable product data table using React.

Start With A Mock

Imagine that we already have a JSON API and a mock from our designer. The mock looks like this: Our JSON API returns some data that looks like this: [ {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"}, {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"}, {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"}, {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"}, {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"}, {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"} ];

Step 1: Break The UI Into A Component Hierarchy

The first thing you'll want to do is to draw boxes around every component (and subcomponent) in the mock and give them all names. If you're working with a designer, they may have already done this, so go talk to them! Their Photoshop layer names may end up being the names of your React components! But how do you know what should be its own component? Use the same techniques for deciding if you should create a new function or object. One such technique is the single responsibility principle, that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents. Since you're often displaying a JSON data model to a user, you'll find that if your model was built correctly, your UI (and therefore your component structure) will map nicely. That's because UI and data models tend to adhere to the same information architecture. Separate your UI into components, where each component matches one piece of your data model. You'll see here that we have five components in our app. We've italicized the data each component represents.
  1. FilterableProductTable (orange): contains the entirety of the example
  2. SearchBar (blue): receives all user input
  3. ProductTable (green): displays and filters the data collection based on user input
  4. ProductCategoryRow (turquoise): displays a heading for each category
  5. ProductRow (red): displays a row for each product
If you look at ProductTable, you'll see that the table header (containing the ¡°Name¡± and ¡°Price¡± labels) isn't its own component. This is a matter of preference, and there's an argument to be made either way. For this example, we left it as part of ProductTable because it is part of rendering the data collection which is ProductTable's responsibility. However, if this header grows to be complex (e.g., if we were to add affordances for sorting), it would certainly make sense to make this its own ProductTableHeader component. Now that we've identified the components in our mock, let's arrange them into a hierarchy. Components that appear within another component in the mock should appear as a child in the hierarchy:

Step 2: Build A Static Version in React

See the Pen Thinking In React: Step 2 on CodePen. Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why. To build a static version of your app that renders your data model, you'll want to build components that reuse other components and pass data using props. props are a way of passing data from parent to child. If you're familiar with the concept of state, don't use state at all to build this static version. State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app, you don't need it. You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with FilterableProductTable) or with the ones lower in it (ProductRow). In simpler examples, it's usually easier to go top-down, and on larger projects, it's easier to go bottom-up and write tests as you build. At the end of this step, you'll have a library of reusable components that render your data model. The components will only have render() methods since this is a static version of your app. The component at the top of the hierarchy (FilterableProductTable) will take your data model as a prop. If you make a change to your underlying data model and call ReactDOM.render() again, the UI will be updated. You can see how your UI is updated and where to make changes. React's one-way data flow (also called one-way binding) keeps everything modular and fast. Refer to the React docs if you need help executing this step.

A Brief Interlude: Props vs State

There are two types of ¡°model¡± data in React: props and state. It's important to understand the distinction between the two; skim the official React docs if you aren't sure what the difference is. See also FAQ: What is the difference between state and props?

Step 3: Identify The Minimal (but complete) Representation Of UI State

To make your UI interactive, you need to be able to trigger changes to your underlying data model. React achieves this with state. To build your app correctly, you first need to think of the minimal set of mutable state that your app needs. The key here is DRY: Don't Repeat Yourself. Figure out the absolute minimal representation of the state your application needs and compute everything else you need on-demand. For example, if you're building a TODO list, keep an array of the TODO items around; don't keep a separate state variable for the count. Instead, when you want to render the TODO count, take the length of the TODO items array. Think of all of the pieces of data in our example application. We have: Let's go through each one and figure out which one is state. Ask three questions about each piece of data:
  1. Is it passed in from a parent via props? If so, it probably isn't state.
  2. Does it remain unchanged over time? If so, it probably isn't state.
  3. Can you compute it based on any other state or props in your component? If so, it isn't state.
The original list of products is passed in as props, so that's not state. The search text and the checkbox seem to be state since they change over time and can't be computed from anything. And finally, the filtered list of products isn't state because it can be computed by combining the original list of products with the search text and value of the checkbox. So finally, our state is:

Step 4: Identify Where Your State Should Live

See the Pen Thinking In React: Step 4 on CodePen. OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or owns, this state. Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. This is often the most challenging part for newcomers to understand, so follow these steps to figure it out: For each piece of state in your application: Let's run through this strategy for our application: Cool, so we've decided that our state lives in FilterableProductTable. First, add an instance property this.state = {filterText: '', inStockOnly: false} to FilterableProductTable's constructor to reflect the initial state of your application. Then, pass filterText and inStockOnly to ProductTable and SearchBar as a prop. Finally, use these props to filter the rows in ProductTable and set the values of the form fields in SearchBar. You can start seeing how your application will behave: set filterText to "ball" and refresh your app. You'll see that the data table is updated correctly.

Step 5: Add Inverse Data Flow

See the Pen Thinking In React: Step 5 on CodePen. So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in FilterableProductTable. React makes this data flow explicit to help you understand how your program works, but it does require a little more typing than traditional two-way data binding. If you try to type or check the box in the current version of the example, you'll see that React ignores your input. This is intentional, as we've set the value prop of the input to always be equal to the state passed in from FilterableProductTable. Let's think about what we want to happen. We want to make sure that whenever the user changes the form, we update the state to reflect the user input. Since components should only update their own state, FilterableProductTable will pass callbacks to SearchBar that will fire whenever the state should be updated. We can use the onChange event on the inputs to be notified of it. The callbacks passed by FilterableProductTable will call setState(), and the app will be updated.

And That's It

Hopefully, this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you're used to, remember that code is read far more than it's written, and it's less difficult to read this modular, explicit code. As you start to build large libraries of components, you'll appreciate this explicitness and modularity, and with code reuse, your lines of code will start to shrink. :)

Accessibility

Why Accessibility?

Web accessibility (also referred to as a11y) is the design and creation of websites that can be used by everyone. Accessibility support is necessary to allow assistive technology to interpret web pages. React fully supports building accessible websites, often by using standard HTML techniques.

Standards and Guidelines

WCAG

The Web Content Accessibility Guidelines provides guidelines for creating accessible web sites. The following WCAG checklists provide an overview:

WAI-ARIA

The Web Accessibility Initiative - Accessible Rich Internet Applications document contains techniques for building fully accessible JavaScript widgets. Note that all aria-* HTML attributes are fully supported in JSX. Whereas most DOM properties and attributes in React are camelCased, these attributes should be hyphen-cased (also known as kebab-case, lisp-case, etc) as they are in plain HTML: <input type="text" aria-label={labelText} aria-required="true" onChange={onchangeHandler} value={inputValue} name="name" />

Semantic HTML

Semantic HTML is the foundation of accessibility in a web application. Using the various HTML elements to reinforce the meaning of information in our websites will often give us accessibility for free. Sometimes we break HTML semantics when we add <div> elements to our JSX to make our React code work, especially when working with lists (<ol>, <ul> and <dl>) and the HTML <table>. In these cases we should rather use React Fragments to group together multiple elements. For example, import React, { Fragment } from 'react'; function ListItem({ item }) { return ( <Fragment> <dt>{item.term}</dt> <dd>{item.description}</dd> </Fragment> ); } function Glossary(props) { return ( <dl> {props.items.map(item => ( <ListItem item={item} key={item.id} /> ))} </dl> ); } You can map a collection of items to an array of fragments as you would any other type of element as well: function Glossary(props) { return ( <dl> {props.items.map(item => ( // Fragments should also have a `key` prop when mapping collections <Fragment key={item.id}> <dt>{item.term}</dt> <dd>{item.description}</dd> </Fragment> ))} </dl> ); } When you don't need any props on the Fragment tag you can use the short syntax, if your tooling supports it: function ListItem({ item }) { return ( <> <dt>{item.term}</dt> <dd>{item.description}</dd> </> ); } For more info, see the Fragments documentation.

Accessible Forms

Labeling

Every HTML form control, such as <input> and <textarea>, needs to be labeled accessibly. We need to provide descriptive labels that are also exposed to screen readers. The following resources show us how to do this: Although these standard HTML practices can be directly used in React, note that the for attribute is written as htmlFor in JSX: <label htmlFor="namedInput">Name:</label><input>

Notifying the user of errors

Error situations need to be understood by all users. The following link shows us how to expose error texts to screen readers as well:
  • The W3C demonstrates user notifications
  • WebAIM looks at form validation

Focus Control

Ensure that your web application can be fully operated with the keyboard only:
  • WebAIM talks about keyboard accessibility

Keyboard focus and focus outline

Keyboard focus refers to the current element in the DOM that is selected to accept input from the keyboard. We see it everywhere as a focus outline similar to that shown in the following image: Only ever use CSS that removes this outline, for example by setting outline: 0, if you are replacing it with another focus outline implementation.

Mechanisms to skip to desired content

Provide a mechanism to allow users to skip past navigation sections in your application as this assists and speeds up keyboard navigation. Skiplinks or Skip Navigation Links are hidden navigation links that only become visible when keyboard users interact with the page. They are very easy to implement with internal page anchors and some styling:
  • WebAIM - Skip Navigation Links
Also use landmark elements and roles, such as <main> and <aside>, to demarcate page regions as assistive technology allow the user to quickly navigate to these sections. Read more about the use of these elements to enhance accessibility here:
  • Accessible Landmarks

Programmatically managing focus

Our React applications continuously modify the HTML DOM during runtime, sometimes leading to keyboard focus being lost or set to an unexpected element. In order to repair this, we need to programmatically nudge the keyboard focus in the right direction. For example, by resetting keyboard focus to a button that opened a modal window after that modal window is closed. MDN Web Docs takes a look at this and describes how we can build keyboard-navigable JavaScript widgets. To set focus in React, we can use Refs to DOM elements. Using this, we first create a ref to an element in the JSX of a component class: class CustomTextInput extends React.Component { constructor(props) { super(props); // Create a ref to store the textInput DOM element this.textInput = React.createRef(); } render() { // Use the `ref` callback to store a reference to the text input DOM // element in an instance field (for example, this.textInput). return ( <input type="text" ref={this.textInput} /> ); } } Then we can focus it elsewhere in our component when needed: focus() { // Explicitly focus the text input using the raw DOM API // Note: we're accessing "current" to get the DOM node this.textInput.current.focus(); } Sometimes a parent component needs to set focus to an element in a child component. We can do this by exposing DOM refs to parent components through a special prop on the child component that forwards the parent's ref to the child's DOM node. function CustomTextInput(props) { return ( <div> <input ref={props.inputRef} /> </div> ); } class Parent extends React.Component { constructor(props) { super(props); this.inputElement = React.createRef(); } render() { return ( <CustomTextInput inputRef={this.inputElement} /> ); } } // Now you can set focus when required. this.inputElement.current.focus(); When using a HOC to extend components, it is recommended to forward the ref to the wrapped component using the forwardRef function of React. If a third party HOC does not implement ref forwarding, the above pattern can still be used as a fallback. A great focus management example is the react-aria-modal. This is a relatively rare example of a fully accessible modal window. Not only does it set initial focus on the cancel button (preventing the keyboard user from accidentally activating the success action) and trap keyboard focus inside the modal, it also resets focus back to the element that initially triggered the modal.
Note: While this is a very important accessibility feature, it is also a technique that should be used judiciously. Use it to repair the keyboard focus flow when it is disturbed, not to try and anticipate how users want to use applications.

Mouse and pointer events

Ensure that all functionality exposed through a mouse or pointer event can also be accessed using the keyboard alone. Depending only on the pointer device will lead to many cases where keyboard users cannot use your application. To illustrate this, let's look at a prolific example of broken accessibility caused by click events. This is the outside click pattern, where a user can disable an opened popover by clicking outside the element. This is typically implemented by attaching a click event to the window object that closes the popover: class OuterClickExample extends React.Component { constructor(props) { super(props); this.state = { isOpen: false }; this.toggleContainer = React.createRef(); this.onClickHandler = this.onClickHandler.bind(this); this.onClickOutsideHandler = this.onClickOutsideHandler.bind(this); } componentDidMount() { window.addEventListener('click', this.onClickOutsideHandler); } componentWillUnmount() { window.removeEventListener('click', this.onClickOutsideHandler); } onClickHandler() { this.setState(currentState => ({ isOpen: !currentState.isOpen })); } onClickOutsideHandler(event) { if (this.state.isOpen && !this.toggleContainer.current.contains(event.target)) { this.setState({ isOpen: false }); } } render() { return ( <div ref={this.toggleContainer}> <button onClick={this.onClickHandler}>Select an option</button> {this.state.isOpen && ( <ul> <li>Option 1</li> <li>Option 2</li> <li>Option 3</li> </ul> )} </div> ); } } This may work fine for users with pointer devices, such as a mouse, but operating this with the keyboard alone leads to broken functionality when tabbing to the next element as the window object never receives a click event. This can lead to obscured functionality which blocks users from using your application. The same functionality can be achieved by using appropriate event handlers instead, such as onBlur and onFocus: class BlurExample extends React.Component { constructor(props) { super(props); this.state = { isOpen: false }; this.timeOutId = null; this.onClickHandler = this.onClickHandler.bind(this); this.onBlurHandler = this.onBlurHandler.bind(this); this.onFocusHandler = this.onFocusHandler.bind(this); } onClickHandler() { this.setState(currentState => ({ isOpen: !currentState.isOpen })); } // We close the popover on the next tick by using setTimeout. // This is necessary because we need to first check if // another child of the element has received focus as // the blur event fires prior to the new focus event. onBlurHandler() { this.timeOutId = setTimeout(() => { this.setState({ isOpen: false }); }); } // If a child receives focus, do not close the popover. onFocusHandler() { clearTimeout(this.timeOutId); } render() { // React assists us by bubbling the blur and // focus events to the parent. return ( <div onBlur={this.onBlurHandler} onFocus={this.onFocusHandler}> <button onClick={this.onClickHandler} aria-haspopup="true" aria-expanded={this.state.isOpen}> Select an option </button> {this.state.isOpen && ( <ul> <li>Option 1</li> <li>Option 2</li> <li>Option 3</li> </ul> )} </div> ); } } This code exposes the functionality to both pointer device and keyboard users. Also note the added aria-* props to support screen-reader users. For simplicity's sake the keyboard events to enable arrow key interaction of the popover options have not been implemented. This is one example of many cases where depending on only pointer and mouse events will break functionality for keyboard users. Always testing with the keyboard will immediately highlight the problem areas which can then be fixed by using keyboard aware event handlers.

More Complex Widgets

A more complex user experience should not mean a less accessible one. Whereas accessibility is most easily achieved by coding as close to HTML as possible, even the most complex widget can be coded accessibly. Here we require knowledge of ARIA Roles as well as ARIA States and Properties. These are toolboxes filled with HTML attributes that are fully supported in JSX and enable us to construct fully accessible, highly functional React components. Each type of widget has a specific design pattern and is expected to function in a certain way by users and user agents alike:
  • WAI-ARIA Authoring Practices - Design Patterns and Widgets
  • Heydon Pickering - ARIA Examples
  • Inclusive Components

Other Points for Consideration

Setting the language

Indicate the human language of page texts as screen reader software uses this to select the correct voice settings:
  • WebAIM - Document Language

Setting the document title

Set the document <title> to correctly describe the current page content as this ensures that the user remains aware of the current page context:
  • WCAG - Understanding the Document Title Requirement
We can set this in React using the React Document Title Component.

Color contrast

Ensure that all readable text on your website has sufficient color contrast to remain maximally readable by users with low vision:
  • WCAG - Understanding the Color Contrast Requirement
  • Everything About Color Contrast And Why You Should Rethink It
  • A11yProject - What is Color Contrast
It can be tedious to manually calculate the proper color combinations for all cases in your website so instead, you can calculate an entire accessible color palette with Colorable. Both the aXe and WAVE tools mentioned below also include color contrast tests and will report on contrast errors. If you want to extend your contrast testing abilities you can use these tools:
  • WebAIM - Color Contrast Checker
  • The Paciello Group - Color Contrast Analyzer

Development and Testing Tools

There are a number of tools we can use to assist in the creation of accessible web applications.

The keyboard

By far the easiest and also one of the most important checks is to test if your entire website can be reached and used with the keyboard alone. Do this by:
  1. Disconnecting your mouse.
  2. Using Tab and Shift+Tab to browse.
  3. Using Enter to activate elements.
  4. Where required, using your keyboard arrow keys to interact with some elements, such as menus and dropdowns.

Development assistance

We can check some accessibility features directly in our JSX code. Often intellisense checks are already provided in JSX aware IDE's for the ARIA roles, states and properties. We also have access to the following tool:
eslint-plugin-jsx-a11y
The eslint-plugin-jsx-a11y plugin for ESLint provides AST linting feedback regarding accessibility issues in your JSX. Many IDE's allow you to integrate these findings directly into code analysis and source code windows. Create React App has this plugin with a subset of rules activated. If you want to enable even more accessibility rules, you can create an .eslintrc file in the root of your project with this content: { "extends": ["react-app", "plugin:jsx-a11y/recommended"], "plugins": ["jsx-a11y"] }

Testing accessibility in the browser

A number of tools exist that can run accessibility audits on web pages in your browser. Please use them in combination with other accessibility checks mentioned here as they can only test the technical accessibility of your HTML.
aXe, aXe-core and react-axe
Deque Systems offers aXe-core for automated and end-to-end accessibility tests of your applications. This module includes integrations for Selenium. The Accessibility Engine or aXe, is an accessibility inspector browser extension built on aXe-core. You can also use the react-axe module to report these accessibility findings directly to the console while developing and debugging.
WebAIM WAVE
The Web Accessibility Evaluation Tool is another accessibility browser extension.
Accessibility inspectors and the Accessibility Tree
The Accessibility Tree is a subset of the DOM tree that contains accessible objects for every DOM element that should be exposed to assistive technology, such as screen readers. In some browsers we can easily view the accessibility information for each element in the accessibility tree:
  • Using the Accessibility Inspector in Firefox
  • Using the Accessibility Inspector in Chrome
  • Using the Accessibility Inspector in OS X Safari

Screen readers

Testing with a screen reader should form part of your accessibility tests. Please note that browser / screen reader combinations matter. It is recommended that you test your application in the browser best suited to your screen reader of choice.

Commonly Used Screen Readers

NVDA in Firefox
NonVisual Desktop Access or NVDA is an open source Windows screen reader that is widely used. Refer to the following guides on how to best use NVDA:
  • WebAIM - Using NVDA to Evaluate Web Accessibility
  • Deque - NVDA Keyboard Shortcuts
VoiceOver in Safari
VoiceOver is an integrated screen reader on Apple devices. Refer to the following guides on how to activate and use VoiceOver:
  • WebAIM - Using VoiceOver to Evaluate Web Accessibility
  • Deque - VoiceOver for OS X Keyboard Shortcuts
  • Deque - VoiceOver for iOS Shortcuts
JAWS in Internet Explorer
Job Access With Speech or JAWS, is a prolifically used screen reader on Windows. Refer to the following guides on how to best use JAWS:
  • WebAIM - Using JAWS to Evaluate Web Accessibility
  • Deque - JAWS Keyboard Shortcuts

Other Screen Readers

ChromeVox in Google Chrome
ChromeVox is an integrated screen reader on Chromebooks and is available as an extension for Google Chrome. Refer to the following guides on how best to use ChromeVox:
  • Google Chromebook Help - Use the Built-in Screen Reader
  • ChromeVox Classic Keyboard Shortcuts Reference

Code-Splitting

Bundling

Most React apps will have their files ¡°bundled¡± using tools like Webpack, Rollup or Browserify. Bundling is the process of following imported files and merging them into a single file: a ¡°bundle¡±. This bundle can then be included on a webpage to load an entire app at once.
Example
App: // app.js import { add } from './math.js'; console.log(add(16, 26)); // 42 // math.js export function add(a, b) { return a + b; } Bundle: function add(a, b) { return a + b; } console.log(add(16, 26)); // 42
Note: Your bundles will end up looking a lot different than this.
If you're using Create React App, Next.js, Gatsby, or a similar tool, you will have a Webpack setup out of the box to bundle your app. If you aren't, you'll need to setup bundling yourself. For example, see the Installation and Getting Started guides on the Webpack docs.

Code Splitting

Bundling is great, but as your app grows, your bundle will grow too. Especially if you are including large third-party libraries. You need to keep an eye on the code you are including in your bundle so that you don't accidentally make it so large that your app takes a long time to load. To avoid winding up with a large bundle, it's good to get ahead of the problem and start ¡°splitting¡± your bundle. Code-Splitting is a feature supported by bundlers like Webpack, Rollup and Browserify (via factor-bundle) which can create multiple bundles that can be dynamically loaded at runtime. Code-splitting your app can help you ¡°lazy-load¡± just the things that are currently needed by the user, which can dramatically improve the performance of your app. While you haven't reduced the overall amount of code in your app, you've avoided loading code that the user may never need, and reduced the amount of code needed during the initial load.

import()

The best way to introduce code-splitting into your app is through the dynamic import() syntax. Before: import { add } from './math'; console.log(add(16, 26)); After: import("./math").then(math => { console.log(math.add(16, 26)); }); When Webpack comes across this syntax, it automatically starts code-splitting your app. If you're using Create React App, this is already configured for you and you can start using it immediately. It's also supported out of the box in Next.js. If you're setting up Webpack yourself, you'll probably want to read Webpack's guide on code splitting. Your Webpack config should look vaguely like this. When using Babel, you'll need to make sure that Babel can parse the dynamic import syntax but is not transforming it. For that you will need @babel/plugin-syntax-dynamic-import.

React.lazy

Note: React.lazy and Suspense are not yet available for server-side rendering. If you want to do code-splitting in a server rendered app, we recommend Loadable Components. It has a nice guide for bundle splitting with server-side rendering.
The React.lazy function lets you render a dynamic import as a regular component. Before: import OtherComponent from './OtherComponent'; After: const OtherComponent = React.lazy(() => import('./OtherComponent')); This will automatically load the bundle containing the OtherComponent when this component is first rendered. React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component. The lazy component should then be rendered inside a Suspense component, which allows us to show some fallback content (such as a loading indicator) while we're waiting for the lazy component to load. import React, { Suspense } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> </div> ); } The fallback prop accepts any React elements that you want to render while waiting for the component to load. You can place the Suspense component anywhere above the lazy component. You can even wrap multiple lazy components with a single Suspense component. import React, { Suspense } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent')); const AnotherComponent = React.lazy(() => import('./AnotherComponent')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <section> <OtherComponent /> <AnotherComponent /> </section> </Suspense> </div> ); }

Error boundaries

If the other module fails to load (for example, due to network failure), it will trigger an error. You can handle these errors to show a nice user experience and manage recovery with Error Boundaries. Once you've created your Error Boundary, you can use it anywhere above your lazy components to display an error state when there's a network error. import React, { Suspense } from 'react'; import MyErrorBoundary from './MyErrorBoundary'; const OtherComponent = React.lazy(() => import('./OtherComponent')); const AnotherComponent = React.lazy(() => import('./AnotherComponent')); const MyComponent = () => ( <div> <MyErrorBoundary> <Suspense fallback={<div>Loading...</div>}> <section> <OtherComponent /> <AnotherComponent /> </section> </Suspense> </MyErrorBoundary> </div> );

Route-based code splitting

Deciding where in your app to introduce code splitting can be a bit tricky. You want to make sure you choose places that will split bundles evenly, but won't disrupt the user experience. A good place to start is with routes. Most people on the web are used to page transitions taking some amount of time to load. You also tend to be re-rendering the entire page at once so your users are unlikely to be interacting with other elements on the page at the same time. Here's an example of how to setup route-based code splitting into your app using libraries like React Router with React.lazy. import React, { Suspense, lazy } from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; const Home = lazy(() => import('./routes/Home')); const About = lazy(() => import('./routes/About')); const App = () => ( <Router> <Suspense fallback={<div>Loading...</div>}> <Switch> <Route exact path="/" component={Home}/> <Route path="/about" component={About}/> </Switch> </Suspense> </Router> );

Named Exports

React.lazy currently only supports default exports. If the module you want to import uses named exports, you can create an intermediate module that reexports it as the default. This ensures that tree shaking keeps working and that you don't pull in unused components. // ManyComponents.js export const MyComponent = /* ... */; export const MyUnusedComponent = /* ... */; // MyComponent.js export { MyComponent as default } from "./ManyComponents.js"; // MyApp.js import React, { lazy } from 'react'; const MyComponent = lazy(() => import("./MyComponent.js"));

Context

Context provides a way to pass data through the component tree without having to pass props down manually at every level. In a typical React application, data is passed top-down (parent to child) via props, but this can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.
  • When to Use Context
  • Before You Use Context
  • API
    • React.createContext
    • Context.Provider
    • Class.contextType
    • Context.Consumer
    • Context.displayName
  • Examples
    • Dynamic Context
    • Updating Context from a Nested Component
    • Consuming Multiple Contexts
  • Caveats
  • Legacy API

When to Use Context

Context is designed to share data that can be considered ¡°global¡± for a tree of React components, such as the current authenticated user, theme, or preferred language. For example, in the code below we manually thread through a ¡°theme¡± prop in order to style the Button component: class App extends React.Component { render() { return <Toolbar theme="dark" />; } } function Toolbar(props) { // The Toolbar component must take an extra "theme" prop // and pass it to the ThemedButton. This can become painful // if every single button in the app needs to know the theme // because it would have to be passed through all components. return ( <div> <ThemedButton theme={props.theme} /> </div> ); } class ThemedButton extends React.Component { render() { return <Button theme={this.props.theme} />; } } Using context, we can avoid passing props through intermediate elements: // Context lets us pass a value deep into the component tree// without explicitly threading it through every component.// Create a context for the current theme (with "light" as the default).const ThemeContext = React.createContext('light'); class App extends React.Component { render() { // Use a Provider to pass the current theme to the tree below. // Any component can read it, no matter how deep it is. // In this example, we're passing "dark" as the current value. return ( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ); } } // A component in the middle doesn't have to// pass the theme down explicitly anymore.function Toolbar() { return ( <div> <ThemedButton /> </div> ); } class ThemedButton extends React.Component { // Assign a contextType to read the current theme context. // React will find the closest theme Provider above and use its value. // In this example, the current theme is "dark". static contextType = ThemeContext; render() { return <Button theme={this.context} />; } }

Before You Use Context

Context is primarily used when some data needs to be accessible by many components at different nesting levels. Apply it sparingly because it makes component reuse more difficult. If you only want to avoid passing some props through many levels, component composition is often a simpler solution than context. For example, consider a Page component that passes a user and avatarSize prop several levels down so that deeply nested Link and Avatar components can read it: <Page user={user} avatarSize={avatarSize} /> // ... which renders ... <PageLayout user={user} avatarSize={avatarSize} /> // ... which renders ... <NavigationBar user={user} avatarSize={avatarSize} /> // ... which renders ... <Link href={user.permalink}> <Avatar user={user} size={avatarSize} /> </Link> It might feel redundant to pass down the user and avatarSize props through many levels if in the end only the Avatar component really needs it. It's also annoying that whenever the Avatar component needs more props from the top, you have to add them at all the intermediate levels too. One way to solve this issue without context is to pass down the Avatar component itself so that the intermediate components don't need to know about the user or avatarSize props: function Page(props) { const user = props.user; const userLink = ( <Link href={user.permalink}> <Avatar user={user} size={props.avatarSize} /> </Link> ); return <PageLayout userLink={userLink} />; } // Now, we have: <Page user={user} avatarSize={avatarSize} /> // ... which renders ... <PageLayout userLink={...} /> // ... which renders ... <NavigationBar userLink={...} /> // ... which renders ... {props.userLink} With this change, only the top-most Page component needs to know about the Link and Avatar components' use of user and avatarSize. This inversion of control can make your code cleaner in many cases by reducing the amount of props you need to pass through your application and giving more control to the root components. However, this isn't the right choice in every case: moving more complexity higher in the tree makes those higher-level components more complicated and forces the lower-level components to be more flexible than you may want. You're not limited to a single child for a component. You may pass multiple children, or even have multiple separate ¡°slots¡± for children, as documented here: function Page(props) { const user = props.user; const content = <Feed user={user} />; const topBar = ( <NavigationBar> <Link href={user.permalink}> <Avatar user={user} size={props.avatarSize} /> </Link> </NavigationBar> ); return ( <PageLayout topBar={topBar} content={content} /> ); } This pattern is sufficient for many cases when you need to decouple a child from its immediate parents. You can take it even further with render props if the child needs to communicate with the parent before rendering. However, sometimes the same data needs to be accessible by many components in the tree, and at different nesting levels. Context lets you ¡°broadcast¡± such data, and changes to it, to all components below. Common examples where using context might be simpler than the alternatives include managing the current locale, theme, or a data cache.

API

React.createContext

const MyContext = React.createContext(defaultValue); Creates a Context object. When React renders a component that subscribes to this Context object it will read the current context value from the closest matching Provider above it in the tree. The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Note: passing undefined as a Provider value does not cause consuming components to use defaultValue.

Context.Provider

<MyContext.Provider value={/* some value */}> Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree. All consumers that are descendants of a Provider will re-render whenever the Provider's value prop changes. The propagation from Provider to its descendant consumers (including .contextType and useContext) is not subject to the shouldComponentUpdate method, so the consumer is updated even when an ancestor component skips an update. Changes are determined by comparing the new and old values using the same algorithm as Object.is.
Note The way changes are determined can cause some issues when passing objects as value: see Caveats.

Class.contextType

class MyClass extends React.Component { componentDidMount() { let value = this.context; /* perform a side-effect at mount using the value of MyContext */ } componentDidUpdate() { let value = this.context; /* ... */ } componentWillUnmount() { let value = this.context; /* ... */ } render() { let value = this.context; /* render something based on the value of MyContext */ } } MyClass.contextType = MyContext; The contextType property on a class can be assigned a Context object created by React.createContext(). This lets you consume the nearest current value of that Context type using this.context. You can reference this in any of the lifecycle methods including the render function.
Note: You can only subscribe to a single context using this API. If you need to read more than one see Consuming Multiple Contexts. If you are using the experimental public class fields syntax, you can use a static class field to initialize your contextType.
class MyClass extends React.Component { static contextType = MyContext; render() { let value = this.context; /* render something based on the value */ } }

Context.Consumer

<MyContext.Consumer> {value => /* render something based on the context value */} </MyContext.Consumer> A React component that subscribes to context changes. This lets you subscribe to a context within a function component. Requires a function as a child. The function receives the current context value and returns a React node. The value argument passed to the function will be equal to the value prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the value argument will be equal to the defaultValue that was passed to createContext().
Note For more information about the ¡®function as a child' pattern, see render props.

Context.displayName

Context object accepts a displayName string property. React DevTools uses this string to determine what to display for the context. For example, the following component will appear as MyDisplayName in the DevTools: const MyContext = React.createContext(/* some value */); MyContext.displayName = 'MyDisplayName'; <MyContext.Provider> // "MyDisplayName.Provider" in DevTools <MyContext.Consumer> // "MyDisplayName.Consumer" in DevTools

Examples

Dynamic Context

A more complex example with dynamic values for the theme: theme-context.js export const themes = { light: { foreground: '#000000', background: '#eeeeee', }, dark: { foreground: '#ffffff', background: '#222222', }, }; export const ThemeContext = React.createContext( themes.dark // default value); themed-button.js import {ThemeContext} from './theme-context'; class ThemedButton extends React.Component { render() { let props = this.props; let theme = this.context; return ( <button {...props} style={{backgroundColor: theme.background}} /> ); } } ThemedButton.contextType = ThemeContext; export default ThemedButton; app.js import {ThemeContext, themes} from './theme-context'; import ThemedButton from './themed-button'; // An intermediate component that uses the ThemedButton function Toolbar(props) { return ( <ThemedButton onClick={props.changeTheme}> Change Theme </ThemedButton> ); } class App extends React.Component { constructor(props) { super(props); this.state = { theme: themes.light, }; this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === themes.dark ? themes.light : themes.dark, })); }; } render() { // The ThemedButton button inside the ThemeProvider // uses the theme from state while the one outside uses // the default dark theme return ( <Page> <ThemeContext.Provider value={this.state.theme}> <Toolbar changeTheme={this.toggleTheme} /> </ThemeContext.Provider> <Section> <ThemedButton /> </Section> </Page> ); } } ReactDOM.render(<App />, document.root);

Updating Context from a Nested Component

It is often necessary to update the context from a component that is nested somewhere deeply in the component tree. In this case you can pass a function down through the context to allow consumers to update the context: theme-context.js // Make sure the shape of the default value passed to // createContext matches the shape that the consumers expect! export const ThemeContext = React.createContext({ theme: themes.dark, toggleTheme: () => {},}); theme-toggler-button.js import {ThemeContext} from './theme-context'; function ThemeTogglerButton() { // The Theme Toggler Button receives not only the theme // but also a toggleTheme function from the context return ( <ThemeContext.Consumer> {({theme, toggleTheme}) => ( <button onClick={toggleTheme} style={{backgroundColor: theme.background}}> Toggle Theme </button> )} </ThemeContext.Consumer> ); } export default ThemeTogglerButton; app.js import {ThemeContext, themes} from './theme-context'; import ThemeTogglerButton from './theme-toggler-button'; class App extends React.Component { constructor(props) { super(props); this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === themes.dark ? themes.light : themes.dark, })); }; // State also contains the updater function so it will // be passed down into the context provider this.state = { theme: themes.light, toggleTheme: this.toggleTheme, }; } render() { // The entire state is passed to the provider return ( <ThemeContext.Provider value={this.state}> <Content /> </ThemeContext.Provider> ); } } function Content() { return ( <div> <ThemeTogglerButton /> </div> ); } ReactDOM.render(<App />, document.root);

Consuming Multiple Contexts

To keep context re-rendering fast, React needs to make each context consumer a separate node in the tree. // Theme context, default to light theme const ThemeContext = React.createContext('light'); // Signed-in user context const UserContext = React.createContext({ name: 'Guest', }); class App extends React.Component { render() { const {signedInUser, theme} = this.props; // App component that provides initial context values return ( <ThemeContext.Provider value={theme}> <UserContext.Provider value={signedInUser}> <Layout /> </UserContext.Provider> </ThemeContext.Provider> ); } } function Layout() { return ( <div> <Sidebar /> <Content /> </div> ); } // A component may consume multiple contexts function Content() { return ( <ThemeContext.Consumer> {theme => ( <UserContext.Consumer> {user => ( <ProfilePage user={user} theme={theme} /> )} </UserContext.Consumer> )} </ThemeContext.Consumer> ); } If two or more context values are often used together, you might want to consider creating your own render prop component that provides both.

Caveats

Because context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider's parent re-renders. For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for value: class App extends React.Component { render() { return ( <MyContext.Provider value={{something: 'something'}}> <Toolbar /> </MyContext.Provider> ); } } To get around this, lift the value into the parent's state: class App extends React.Component { constructor(props) { super(props); this.state = { value: {something: 'something'}, }; } render() { return ( <Provider value={this.state.value}> <Toolbar /> </Provider> ); } }

Legacy API

Note React previously shipped with an experimental context API. The old API will be supported in all 16.x releases, but applications using it should migrate to the new version. The legacy API will be removed in a future major React version. Read the legacy context docs here.

Error Boundaries

In the past, JavaScript errors inside components used to corrupt React's internal state and cause it to emit cryptic errors on next renders. These errors were always caused by an earlier error in the application code, but React did not provide a way to handle them gracefully in components, and could not recover from them.

Introducing Error Boundaries

A JavaScript error in a part of the UI shouldn't break the whole app. To solve this problem for React users, React 16 introduces a new concept of an ¡°error boundary¡±. Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
Note Error boundaries do not catch errors for:
  • Event handlers (learn more)
  • Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
  • Server side rendering
  • Errors thrown in the error boundary itself (rather than its children)
A class component becomes an error boundary if it defines either (or both) of the lifecycle methods static getDerivedStateFromError() or componentDidCatch(). Use static getDerivedStateFromError() to render a fallback UI after an error has been thrown. Use componentDidCatch() to log error information. class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; } componentDidCatch(error, errorInfo) { // You can also log the error to an error reporting service logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h2>Something went wrong.</h2>; } return this.props.children; } } Then you can use it as a regular component: <ErrorBoundary> <MyWidget /> </ErrorBoundary> Error boundaries work like a JavaScript catch {} block, but for components. Only class components can be error boundaries. In practice, most of the time you'll want to declare an error boundary component once and use it throughout your application. Note that error boundaries only catch errors in the components below them in the tree. An error boundary can't catch an error within itself. If an error boundary fails trying to render the error message, the error will propagate to the closest error boundary above it. This, too, is similar to how catch {} block works in JavaScript.

Live Demo

Check out this example of declaring and using an error boundary with React 16.

Where to Place Error Boundaries

The granularity of error boundaries is up to you. You may wrap top-level route components to display a ¡°Something went wrong¡± message to the user, just like server-side frameworks often handle crashes. You may also wrap individual widgets in an error boundary to protect them from crashing the rest of the application.

New Behavior for Uncaught Errors

This change has an important implication. As of React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree. We debated this decision, but in our experience it is worse to leave corrupted UI in place than to completely remove it. For example, in a product like Messenger leaving the broken UI visible could lead to somebody sending a message to the wrong person. Similarly, it is worse for a payments app to display a wrong amount than to render nothing. This change means that as you migrate to React 16, you will likely uncover existing crashes in your application that have been unnoticed before. Adding error boundaries lets you provide better user experience when something goes wrong. For example, Facebook Messenger wraps content of the sidebar, the info panel, the conversation log, and the message input into separate error boundaries. If some component in one of these UI areas crashes, the rest of them remain interactive. We also encourage you to use JS error reporting services (or build your own) so that you can learn about unhandled exceptions as they happen in production, and fix them.

Component Stack Traces

React 16 prints all errors that occurred during rendering to the console in development, even if the application accidentally swallows them. In addition to the error message and the JavaScript stack, it also provides component stack traces. Now you can see where exactly in the component tree the failure has happened: You can also see the filenames and line numbers in the component stack trace. This works by default in Create React App projects: If you don't use Create React App, you can add this plugin manually to your Babel configuration. Note that it's intended only for development and must be disabled in production.
Note Component names displayed in the stack traces depend on the Function.name property. If you support older browsers and devices which may not yet provide this natively (e.g. IE 11), consider including a Function.name polyfill in your bundled application, such as function.name-polyfill. Alternatively, you may explicitly set the displayName property on all your components.

How About try/catch?

try / catch is great but it only works for imperative code: try { showButton(); } catch (error) { // ... } However, React components are declarative and specify what should be rendered: <Button /> Error boundaries preserve the declarative nature of React, and behave as you would expect. For example, even if an error occurs in a componentDidUpdate method caused by a setState somewhere deep in the tree, it will still correctly propagate to the closest error boundary.

How About Event Handlers?

Error boundaries do not catch errors inside event handlers. React doesn't need error boundaries to recover from errors in event handlers. Unlike the render method and lifecycle methods, the event handlers don't happen during rendering. So if they throw, React still knows what to display on the screen. If you need to catch an error inside event handler, use the regular JavaScript try / catch statement: class MyComponent extends React.Component { constructor(props) { super(props); this.state = { error: null }; this.handleClick = this.handleClick.bind(this); } handleClick() { try { // Do something that could throw } catch (error) { this.setState({ error }); } } render() { if (this.state.error) { return <h2>Caught an error.</h2> } return <button onClick={this.handleClick}>Click Me</button> } } Note that the above example is demonstrating regular JavaScript behavior and doesn't use error boundaries.

Naming Changes from React 15

React 15 included a very limited support for error boundaries under a different method name: unstable_handleError. This method no longer works, and you will need to change it to componentDidCatch in your code starting from the first 16 beta release. For this change, we've provided a codemod to automatically migrate your code.

Forwarding Refs

Ref forwarding is a technique for automatically passing a ref through a component to one of its children. This is typically not necessary for most components in the application. However, it can be useful for some kinds of components, especially in reusable component libraries. The most common scenarios are described below.

Forwarding refs to DOM components

Consider a FancyButton component that renders the native button DOM element: function FancyButton(props) { return ( <button className="FancyButton"> {props.children} </button> ); } React components hide their implementation details, including their rendered output. Other components using FancyButton usually will not need to obtain a ref to the inner button DOM element. This is good because it prevents components from relying on each other's DOM structure too much. Although such encapsulation is desirable for application-level components like FeedStory or Comment, it can be inconvenient for highly reusable ¡°leaf¡± components like FancyButton or MyTextInput. These components tend to be used throughout the application in a similar manner as a regular DOM button and input, and accessing their DOM nodes may be unavoidable for managing focus, selection, or animations. Ref forwarding is an opt-in feature that lets some components take a ref they receive, and pass it further down (in other words, ¡°forward¡± it) to a child. In the example below, FancyButton uses React.forwardRef to obtain the ref passed to it, and then forward it to the DOM button that it renders: const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children} </button> )); // You can now get a ref directly to the DOM button: const ref = React.createRef(); <FancyButton ref={ref}>Click me!</FancyButton>; This way, components using FancyButton can get a ref to the underlying button DOM node and access it if necessary¡ªjust like if they used a DOM button directly. Here is a step-by-step explanation of what happens in the above example:
  1. We create a React ref by calling React.createRef and assign it to a ref variable.
  2. We pass our ref down to <FancyButton ref={ref}> by specifying it as a JSX attribute.
  3. React passes the ref to the (props, ref) => ... function inside forwardRef as a second argument.
  4. We forward this ref argument down to <button ref={ref}> by specifying it as a JSX attribute.
  5. When the ref is attached, ref.current will point to the <button> DOM node.
Note The second ref argument only exists when you define a component with React.forwardRef call. Regular function or class components don't receive the ref argument, and ref is not available in props either. Ref forwarding is not limited to DOM components. You can forward refs to class component instances, too.

Note for component library maintainers

When you start using forwardRef in a component library, you should treat it as a breaking change and release a new major version of your library. This is because your library likely has an observably different behavior (such as what refs get assigned to, and what types are exported), and this can break apps and other libraries that depend on the old behavior. Conditionally applying React.forwardRef when it exists is also not recommended for the same reasons: it changes how your library behaves and can break your users' apps when they upgrade React itself.

Forwarding refs in higher-order components

This technique can also be particularly useful with higher-order components (also known as HOCs). Let's start with an example HOC that logs component props to the console: function logProps(WrappedComponent) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old props:', prevProps); console.log('new props:', this.props); } render() { return <WrappedComponent {...this.props} />; } } return LogProps; } The ¡°logProps¡± HOC passes all props through to the component it wraps, so the rendered output will be the same. For example, we can use this HOC to log all props that get passed to our ¡°fancy button¡± component: class FancyButton extends React.Component { focus() { // ... } // ... } // Rather than exporting FancyButton, we export LogProps. // It will render a FancyButton though. export default logProps(FancyButton); There is one caveat to the above example: refs will not get passed through. That's because ref is not a prop. Like key, it's handled differently by React. If you add a ref to a HOC, the ref will refer to the outermost container component, not the wrapped component. This means that refs intended for our FancyButton component will actually be attached to the LogProps component: import FancyButton from './FancyButton'; const ref = React.createRef(); // The FancyButton component we imported is the LogProps HOC. // Even though the rendered output will be the same, // Our ref will point to LogProps instead of the inner FancyButton component! // This means we can't call e.g. ref.current.focus() <FancyButton label="Click Me" handleClick={handleClick} ref={ref}/>; Fortunately, we can explicitly forward refs to the inner FancyButton component using the React.forwardRef API. React.forwardRef accepts a render function that receives props and ref parameters and returns a React node. For example: function logProps(Component) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old props:', prevProps); console.log('new props:', this.props); } render() { const {forwardedRef, ...rest} = this.props; // Assign the custom prop "forwardedRef" as a ref return <Component ref={forwardedRef} {...rest} />; } } // Note the second param "ref" provided by React.forwardRef. // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef" // And it can then be attached to the Component. return React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />; });}

Displaying a custom name in DevTools

React.forwardRef accepts a render function. React DevTools uses this function to determine what to display for the ref forwarding component. For example, the following component will appear as ¡±ForwardRef¡± in the DevTools: const WrappedComponent = React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />; }); If you name the render function, DevTools will also include its name (e.g. ¡±ForwardRef(myFunction)¡±): const WrappedComponent = React.forwardRef( function myFunction(props, ref) { return <LogProps {...props} forwardedRef={ref} />; } ); You can even set the function's displayName property to include the component you're wrapping: function logProps(Component) { class LogProps extends React.Component { // ... } function forwardRef(props, ref) { return <LogProps {...props} forwardedRef={ref} />; } // Give this component a more helpful display name in DevTools. // e.g. "ForwardRef(logProps(MyComponent))" const name = Component.displayName || Component.name; forwardRef.displayName = `logProps(${name})`; return React.forwardRef(forwardRef); }

Fragments

A common pattern in React is for a component to return multiple elements. Fragments let you group a list of children without adding extra nodes to the DOM. render() { return ( <React.Fragment> <ChildA /> <ChildB /> <ChildC /> </React.Fragment> ); } There is also a new short syntax for declaring them.

Motivation

A common pattern is for a component to return a list of children. Take this example React snippet: class Table extends React.Component { render() { return ( <table> <tr> <Columns /> </tr> </table> ); } } <Columns /> would need to return multiple <td> elements in order for the rendered HTML to be valid. If a parent div was used inside the render() of <Columns />, then the resulting HTML will be invalid. class Columns extends React.Component { render() { return ( <div> <td>Hello</td> <td>World</td> </div> ); } } results in a <Table /> output of: <table> <tr> <div> <td>Hello</td> <td>World</td> </div> </tr> </table> Fragments solve this problem.

Usage

class Columns extends React.Component { render() { return ( <React.Fragment> <td>Hello</td> <td>World</td> </React.Fragment> ); } } which results in a correct <Table /> output of: <table> <tr> <td>Hello</td> <td>World</td> </tr> </table>

Short Syntax

There is a new, shorter syntax you can use for declaring fragments. It looks like empty tags: class Columns extends React.Component { render() { return ( <> <td>Hello</td> <td>World</td> </> ); } } You can use <></> the same way you'd use any other element except that it doesn't support keys or attributes.

Keyed Fragments

Fragments declared with the explicit <React.Fragment> syntax may have keys. A use case for this is mapping a collection to an array of fragments ¡ª for example, to create a description list: function Glossary(props) { return ( <dl> {props.items.map(item => ( // Without the `key`, React will fire a key warning <React.Fragment key={item.id}> <dt>{item.term}</dt> <dd>{item.description}</dd> </React.Fragment> ))} </dl> ); } key is the only attribute that can be passed to Fragment. In the future, we may add support for additional attributes, such as event handlers.

Live Demo

You can try out the new JSX fragment syntax with this CodePen.

Higher-Order Components

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React's compositional nature. Concretely, a higher-order component is a function that takes a component and returns a new component. const EnhancedComponent = higherOrderComponent(WrappedComponent); Whereas a component transforms props into UI, a higher-order component transforms a component into another component. HOCs are common in third-party React libraries, such as Redux's connect and Relay's createFragmentContainer. In this document, we'll discuss why higher-order components are useful, and how to write your own.

Use HOCs For Cross-Cutting Concerns

Note We previously recommended mixins as a way to handle cross-cutting concerns. We've since realized that mixins create more trouble than they are worth. Read more about why we've moved away from mixins and how you can transition your existing components.
Components are the primary unit of code reuse in React. However, you'll find that some patterns aren't a straightforward fit for traditional components. For example, say you have a CommentList component that subscribes to an external data source to render a list of comments: class CommentList extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { // "DataSource" is some global data source comments: DataSource.getComments() }; } componentDidMount() { // Subscribe to changes DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { // Clean up listener DataSource.removeChangeListener(this.handleChange); } handleChange() { // Update component state whenever the data source changes this.setState({ comments: DataSource.getComments() }); } render() { return ( <div> {this.state.comments.map((comment) => ( <Comment comment={comment} key={comment.id} /> ))} </div> ); } } Later, you write a component for subscribing to a single blog post, which follows a similar pattern: class BlogPost extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { blogPost: DataSource.getBlogPost(props.id) }; } componentDidMount() { DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ blogPost: DataSource.getBlogPost(this.props.id) }); } render() { return <TextBlock text={this.state.blogPost} />; } } CommentList and BlogPost aren't identical ¡ª they call different methods on DataSource, and they render different output. But much of their implementation is the same:
  • On mount, add a change listener to DataSource.
  • Inside the listener, call setState whenever the data source changes.
  • On unmount, remove the change listener.
You can imagine that in a large app, this same pattern of subscribing to DataSource and calling setState will occur over and over again. We want an abstraction that allows us to define this logic in a single place and share it across many components. This is where higher-order components excel. We can write a function that creates components, like CommentList and BlogPost, that subscribe to DataSource. The function will accept as one of its arguments a child component that receives the subscribed data as a prop. Let's call the function withSubscription: const CommentListWithSubscription = withSubscription( CommentList, (DataSource) => DataSource.getComments() ); const BlogPostWithSubscription = withSubscription( BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id) ); The first parameter is the wrapped component. The second parameter retrieves the data we're interested in, given a DataSource and the current props. When CommentListWithSubscription and BlogPostWithSubscription are rendered, CommentList and BlogPost will be passed a data prop with the most current data retrieved from DataSource: // This function takes a component... function withSubscription(WrappedComponent, selectData) { // ...and returns another component... return class extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { data: selectData(DataSource, props) }; } componentDidMount() { // ... that takes care of the subscription... DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ data: selectData(DataSource, this.props) }); } render() { // ... and renders the wrapped component with the fresh data! // Notice that we pass through any additional props return <WrappedComponent data={this.state.data} {...this.props} />; } }; } Note that a HOC doesn't modify the input component, nor does it use inheritance to copy its behavior. Rather, a HOC composes the original component by wrapping it in a container component. A HOC is a pure function with zero side-effects. And that's it! The wrapped component receives all the props of the container, along with a new prop, data, which it uses to render its output. The HOC isn't concerned with how or why the data is used, and the wrapped component isn't concerned with where the data came from. Because withSubscription is a normal function, you can add as many or as few arguments as you like. For example, you may want to make the name of the data prop configurable, to further isolate the HOC from the wrapped component. Or you could accept an argument that configures shouldComponentUpdate, or one that configures the data source. These are all possible because the HOC has full control over how the component is defined. Like components, the contract between withSubscription and the wrapped component is entirely props-based. This makes it easy to swap one HOC for a different one, as long as they provide the same props to the wrapped component. This may be useful if you change data-fetching libraries, for example.

Don't Mutate the Original Component. Use Composition.

Resist the temptation to modify a component's prototype (or otherwise mutate it) inside a HOC. function logProps(InputComponent) { InputComponent.prototype.componentDidUpdate = function(prevProps) { console.log('Current props: ', this.props); console.log('Previous props: ', prevProps); }; // The fact that we're returning the original input is a hint that it has // been mutated. return InputComponent; } // EnhancedComponent will log whenever props are received const EnhancedComponent = logProps(InputComponent); There are a few problems with this. One is that the input component cannot be reused separately from the enhanced component. More crucially, if you apply another HOC to EnhancedComponent that also mutates componentDidUpdate, the first HOC's functionality will be overridden! This HOC also won't work with function components, which do not have lifecycle methods. Mutating HOCs are a leaky abstraction¡ªthe consumer must know how they are implemented in order to avoid conflicts with other HOCs. Instead of mutation, HOCs should use composition, by wrapping the input component in a container component: function logProps(WrappedComponent) { return class extends React.Component { componentDidUpdate(prevProps) { console.log('Current props: ', this.props); console.log('Previous props: ', prevProps); } render() { // Wraps the input component in a container, without mutating it. Good! return <WrappedComponent {...this.props} />; } } } This HOC has the same functionality as the mutating version while avoiding the potential for clashes. It works equally well with class and function components. And because it's a pure function, it's composable with other HOCs, or even with itself. You may have noticed similarities between HOCs and a pattern called container components. Container components are part of a strategy of separating responsibility between high-level and low-level concerns. Containers manage things like subscriptions and state, and pass props to components that handle things like rendering UI. HOCs use containers as part of their implementation. You can think of HOCs as parameterized container component definitions.

Convention: Pass Unrelated Props Through to the Wrapped Component

HOCs add features to a component. They shouldn't drastically alter its contract. It's expected that the component returned from a HOC has a similar interface to the wrapped component. HOCs should pass through props that are unrelated to its specific concern. Most HOCs contain a render method that looks something like this: render() { // Filter out extra props that are specific to this HOC and shouldn't be // passed through const { extraProp, ...passThroughProps } = this.props; // Inject props into the wrapped component. These are usually state values or // instance methods. const injectedProp = someStateOrInstanceMethod; // Pass props to wrapped component return ( <WrappedComponent injectedProp={injectedProp} {...passThroughProps} /> ); } This convention helps ensure that HOCs are as flexible and reusable as possible.

Convention: Maximizing Composability

Not all HOCs look the same. Sometimes they accept only a single argument, the wrapped component: const NavbarWithRouter = withRouter(Navbar); Usually, HOCs accept additional arguments. In this example from Relay, a config object is used to specify a component's data dependencies: const CommentWithRelay = Relay.createContainer(Comment, config); The most common signature for HOCs looks like this: // React Redux's `connect` const ConnectedComment = connect(commentSelector, commentActions)(CommentList); What?! If you break it apart, it's easier to see what's going on. // connect is a function that returns another function const enhance = connect(commentListSelector, commentListActions); // The returned function is a HOC, which returns a component that is connected // to the Redux store const ConnectedComment = enhance(CommentList); In other words, connect is a higher-order function that returns a higher-order component! This form may seem confusing or unnecessary, but it has a useful property. Single-argument HOCs like the one returned by the connect function have the signature Component => Component. Functions whose output type is the same as its input type are really easy to compose together. // Instead of doing this... const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) // ... you can use a function composition utility // compose(f, g, h) is the same as (...args) => f(g(h(...args))) const enhance = compose( // These are both single-argument HOCs withRouter, connect(commentSelector) ) const EnhancedComponent = enhance(WrappedComponent) (This same property also allows connect and other enhancer-style HOCs to be used as decorators, an experimental JavaScript proposal.) The compose utility function is provided by many third-party libraries including lodash (as lodash.flowRight), Redux, and Ramda.

Convention: Wrap the Display Name for Easy Debugging

The container components created by HOCs show up in the React Developer Tools like any other component. To ease debugging, choose a display name that communicates that it's the result of a HOC. The most common technique is to wrap the display name of the wrapped component. So if your higher-order component is named withSubscription, and the wrapped component's display name is CommentList, use the display name WithSubscription(CommentList): function withSubscription(WrappedComponent) { class WithSubscription extends React.Component {/* ... */} WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`; return WithSubscription; } function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component'; }

Caveats

Higher-order components come with a few caveats that aren't immediately obvious if you're new to React.

Don't Use HOCs Inside the render Method

React's diffing algorithm (called Reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from render is identical (===) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they're not equal, the previous subtree is unmounted completely. Normally, you shouldn't need to think about this. But it matters for HOCs because it means you can't apply a HOC to a component within the render method of a component: render() { // A new version of EnhancedComponent is created on every render // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); // That causes the entire subtree to unmount/remount each time! return <EnhancedComponent />; } The problem here isn't just about performance ¡ª remounting a component causes the state of that component and all of its children to be lost. Instead, apply HOCs outside the component definition so that the resulting component is created only once. Then, its identity will be consistent across renders. This is usually what you want, anyway. In those rare cases where you need to apply a HOC dynamically, you can also do it inside a component's lifecycle methods or its constructor.

Static Methods Must Be Copied Over

Sometimes it's useful to define a static method on a React component. For example, Relay containers expose a static method getFragment to facilitate the composition of GraphQL fragments. When you apply a HOC to a component, though, the original component is wrapped with a container component. That means the new component does not have any of the static methods of the original component. // Define a static method WrappedComponent.staticMethod = function() {/*...*/} // Now apply a HOC const EnhancedComponent = enhance(WrappedComponent); // The enhanced component has no static method typeof EnhancedComponent.staticMethod === 'undefined' // true To solve this, you could copy the methods onto the container before returning it: function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} // Must know exactly which method(s) to copy :( Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; } However, this requires you to know exactly which methods need to be copied. You can use hoist-non-react-statics to automatically copy all non-React static methods: import hoistNonReactStatic from 'hoist-non-react-statics'; function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} hoistNonReactStatic(Enhance, WrappedComponent); return Enhance; } Another possible solution is to export the static method separately from the component itself. // Instead of... MyComponent.someFunction = someFunction; export default MyComponent; // ...export the method separately... export { someFunction }; // ...and in the consuming module, import both import MyComponent, { someFunction } from './MyComponent.js';

Refs Aren't Passed Through

While the convention for higher-order components is to pass through all props to the wrapped component, this does not work for refs. That's because ref is not really a prop ¡ª like key, it's handled specially by React. If you add a ref to an element whose component is the result of a HOC, the ref refers to an instance of the outermost container component, not the wrapped component. The solution for this problem is to use the React.forwardRef API (introduced with React 16.3). Learn more about it in the forwarding refs section.

Integrating with Other Libraries

React can be used in any web application. It can be embedded in other applications and, with a little care, other applications can be embedded in React. This guide will examine some of the more common use cases, focusing on integration with jQuery and Backbone, but the same ideas can be applied to integrating components with any existing code.

Integrating with DOM Manipulation Plugins

React is unaware of changes made to the DOM outside of React. It determines updates based on its own internal representation, and if the same DOM nodes are manipulated by another library, React gets confused and has no way to recover. This does not mean it is impossible or even necessarily difficult to combine React with other ways of affecting the DOM, you just have to be mindful of what each is doing. The easiest way to avoid conflicts is to prevent the React component from updating. You can do this by rendering elements that React has no reason to update, like an empty <div />.

How to Approach the Problem

To demonstrate this, let's sketch out a wrapper for a generic jQuery plugin. We will attach a ref to the root DOM element. Inside componentDidMount, we will get a reference to it so we can pass it to the jQuery plugin. To prevent React from touching the DOM after mounting, we will return an empty <div /> from the render() method. The <div /> element has no properties or children, so React has no reason to update it, leaving the jQuery plugin free to manage that part of the DOM: class SomePlugin extends React.Component { componentDidMount() { this.$el = $(this.el); this.$el.somePlugin(); } componentWillUnmount() { this.$el.somePlugin('destroy'); } render() { return <div ref={el => this.el = el} />; } } Note that we defined both componentDidMount and componentWillUnmount lifecycle methods. Many jQuery plugins attach event listeners to the DOM so it's important to detach them in componentWillUnmount. If the plugin does not provide a method for cleanup, you will probably have to provide your own, remembering to remove any event listeners the plugin registered to prevent memory leaks.

Integrating with jQuery Chosen Plugin

For a more concrete example of these concepts, let's write a minimal wrapper for the plugin Chosen, which augments <select> inputs.
Note: Just because it's possible, doesn't mean that it's the best approach for React apps. We encourage you to use React components when you can. React components are easier to reuse in React applications, and often provide more control over their behavior and appearance.
First, let's look at what Chosen does to the DOM. If you call it on a <select> DOM node, it reads the attributes off of the original DOM node, hides it with an inline style, and then appends a separate DOM node with its own visual representation right after the <select>. Then it fires jQuery events to notify us about the changes. Let's say that this is the API we're striving for with our <Chosen> wrapper React component: function Example() { return ( <Chosen onChange={value => console.log(value)}> <option>vanilla</option> <option>chocolate</option> <option>strawberry</option> </Chosen> ); } We will implement it as an uncontrolled component for simplicity. First, we will create an empty component with a render() method where we return <select> wrapped in a <div>: class Chosen extends React.Component { render() { return ( <div> <select className="Chosen-select" ref={el => this.el = el}> {this.props.children} </select> </div> ); } } Notice how we wrapped <select> in an extra <div>. This is necessary because Chosen will append another DOM element right after the <select> node we passed to it. However, as far as React is concerned, <div> always only has a single child. This is how we ensure that React updates won't conflict with the extra DOM node appended by Chosen. It is important that if you modify the DOM outside of React flow, you must ensure React doesn't have a reason to touch those DOM nodes. Next, we will implement the lifecycle methods. We need to initialize Chosen with the ref to the <select> node in componentDidMount, and tear it down in componentWillUnmount: componentDidMount() { this.$el = $(this.el); this.$el.chosen();} componentWillUnmount() { this.$el.chosen('destroy');} Try it on CodePen Note that React assigns no special meaning to the this.el field. It only works because we have previously assigned this field from a ref in the render() method: <select className="Chosen-select" ref={el => this.el = el}> This is enough to get our component to render, but we also want to be notified about the value changes. To do this, we will subscribe to the jQuery change event on the <select> managed by Chosen. We won't pass this.props.onChange directly to Chosen because component's props might change over time, and that includes event handlers. Instead, we will declare a handleChange() method that calls this.props.onChange, and subscribe it to the jQuery change event: componentDidMount() { this.$el = $(this.el); this.$el.chosen(); this.handleChange = this.handleChange.bind(this); this.$el.on('change', this.handleChange);} componentWillUnmount() { this.$el.off('change', this.handleChange); this.$el.chosen('destroy'); } handleChange(e) { this.props.onChange(e.target.value);} Try it on CodePen Finally, there is one more thing left to do. In React, props can change over time. For example, the <Chosen> component can get different children if parent component's state changes. This means that at integration points it is important that we manually update the DOM in response to prop updates, since we no longer let React manage the DOM for us. Chosen's documentation suggests that we can use jQuery trigger() API to notify it about changes to the original DOM element. We will let React take care of updating this.props.children inside <select>, but we will also add a componentDidUpdate() lifecycle method that notifies Chosen about changes in the children list: componentDidUpdate(prevProps) { if (prevProps.children !== this.props.children) { this.$el.trigger("chosen:updated"); } } This way, Chosen will know to update its DOM element when the <select> children managed by React change. The complete implementation of the Chosen component looks like this: class Chosen extends React.Component { componentDidMount() { this.$el = $(this.el); this.$el.chosen(); this.handleChange = this.handleChange.bind(this); this.$el.on('change', this.handleChange); } componentDidUpdate(prevProps) { if (prevProps.children !== this.props.children) { this.$el.trigger("chosen:updated"); } } componentWillUnmount() { this.$el.off('change', this.handleChange); this.$el.chosen('destroy'); } handleChange(e) { this.props.onChange(e.target.value); } render() { return ( <div> <select className="Chosen-select" ref={el => this.el = el}> {this.props.children} </select> </div> ); } } Try it on CodePen

Integrating with Other View Libraries

React can be embedded into other applications thanks to the flexibility of ReactDOM.render(). Although React is commonly used at startup to load a single root React component into the DOM, ReactDOM.render() can also be called multiple times for independent parts of the UI which can be as small as a button, or as large as an app. In fact, this is exactly how React is used at Facebook. This lets us write applications in React piece by piece, and combine them with our existing server-generated templates and other client-side code.

Replacing String-Based Rendering with React

A common pattern in older web applications is to describe chunks of the DOM as a string and insert it into the DOM like so: $el.html(htmlString). These points in a codebase are perfect for introducing React. Just rewrite the string based rendering as a React component. So the following jQuery implementation¡­ $('#container').html('<button id="btn">Say Hello</button>'); $('#btn').click(function() { alert('Hello!'); }); ¡­could be rewritten using a React component: function Button() { return <button id="btn">Say Hello</button>; } ReactDOM.render( <Button />, document.getElementById('container'), function() { $('#btn').click(function() { alert('Hello!'); }); } ); From here you could start moving more logic into the component and begin adopting more common React practices. For example, in components it is best not to rely on IDs because the same component can be rendered multiple times. Instead, we will use the React event system and register the click handler directly on the React <button> element: function Button(props) { return <button onClick={props.onClick}>Say Hello</button>;} function HelloButton() { function handleClick() { alert('Hello!'); } return <Button onClick={handleClick} />;} ReactDOM.render( <HelloButton />, document.getElementById('container') ); Try it on CodePen You can have as many such isolated components as you like, and use ReactDOM.render() to render them to different DOM containers. Gradually, as you convert more of your app to React, you will be able to combine them into larger components, and move some of the ReactDOM.render() calls up the hierarchy.

Embedding React in a Backbone View

Backbone views typically use HTML strings, or string-producing template functions, to create the content for their DOM elements. This process, too, can be replaced with rendering a React component. Below, we will create a Backbone view called ParagraphView. It will override Backbone's render() function to render a React <Paragraph> component into the DOM element provided by Backbone (this.el). Here, too, we are using ReactDOM.render(): function Paragraph(props) { return <p>{props.text}</p>; } const ParagraphView = Backbone.View.extend({ render() { const text = this.model.get('text'); ReactDOM.render(<Paragraph text={text} />, this.el); return this; }, remove() { ReactDOM.unmountComponentAtNode(this.el); Backbone.View.prototype.remove.call(this); } }); Try it on CodePen It is important that we also call ReactDOM.unmountComponentAtNode() in the remove method so that React unregisters event handlers and other resources associated with the component tree when it is detached. When a component is removed from within a React tree, the cleanup is performed automatically, but because we are removing the entire tree by hand, we must call this method.

Integrating with Model Layers

While it is generally recommended to use unidirectional data flow such as React state, Flux, or Redux, React components can use a model layer from other frameworks and libraries.

Using Backbone Models in React Components

The simplest way to consume Backbone models and collections from a React component is to listen to the various change events and manually force an update. Components responsible for rendering models would listen to 'change' events, while components responsible for rendering collections would listen for 'add' and 'remove' events. In both cases, call this.forceUpdate() to rerender the component with the new data. In the example below, the List component renders a Backbone collection, using the Item component to render individual items. class Item extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } handleChange() { this.forceUpdate(); } componentDidMount() { this.props.model.on('change', this.handleChange); } componentWillUnmount() { this.props.model.off('change', this.handleChange); } render() { return <li>{this.props.model.get('text')}</li>; } } class List extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } handleChange() { this.forceUpdate(); } componentDidMount() { this.props.collection.on('add', 'remove', this.handleChange); } componentWillUnmount() { this.props.collection.off('add', 'remove', this.handleChange); } render() { return ( <ul> {this.props.collection.map(model => ( <Item key={model.cid} model={model} /> ))} </ul> ); } } Try it on CodePen

Extracting Data from Backbone Models

The approach above requires your React components to be aware of the Backbone models and collections. If you later plan to migrate to another data management solution, you might want to concentrate the knowledge about Backbone in as few parts of the code as possible. One solution to this is to extract the model's attributes as plain data whenever it changes, and keep this logic in a single place. The following is a higher-order component that extracts all attributes of a Backbone model into state, passing the data to the wrapped component. This way, only the higher-order component needs to know about Backbone model internals, and most components in the app can stay agnostic of Backbone. In the example below, we will make a copy of the model's attributes to form the initial state. We subscribe to the change event (and unsubscribe on unmounting), and when it happens, we update the state with the model's current attributes. Finally, we make sure that if the model prop itself changes, we don't forget to unsubscribe from the old model, and subscribe to the new one. Note that this example is not meant to be exhaustive with regards to working with Backbone, but it should give you an idea for how to approach this in a generic way: function connectToBackboneModel(WrappedComponent) { return class BackboneComponent extends React.Component { constructor(props) { super(props); this.state = Object.assign({}, props.model.attributes); this.handleChange = this.handleChange.bind(this); } componentDidMount() { this.props.model.on('change', this.handleChange); } componentWillReceiveProps(nextProps) { this.setState(Object.assign({}, nextProps.model.attributes)); if (nextProps.model !== this.props.model) { this.props.model.off('change', this.handleChange); nextProps.model.on('change', this.handleChange); } } componentWillUnmount() { this.props.model.off('change', this.handleChange); } handleChange(model) { this.setState(model.changedAttributes()); } render() { const propsExceptModel = Object.assign({}, this.props); delete propsExceptModel.model; return <WrappedComponent {...propsExceptModel} {...this.state} />; } } } To demonstrate how to use it, we will connect a NameInput React component to a Backbone model, and update its firstName attribute every time the input changes: function NameInput(props) { return ( <p> <input value={props.firstName} onChange={props.handleChange} /> <br /> My name is {props.firstName}. </p> ); } const BackboneNameInput = connectToBackboneModel(NameInput); function Example(props) { function handleChange(e) { props.model.set('firstName', e.target.value); } return ( <BackboneNameInput model={props.model} handleChange={handleChange} /> ); } const model = new Backbone.Model({ firstName: 'Frodo' }); ReactDOM.render( <Example model={model} />, document.getElementById('root') ); Try it on CodePen This technique is not limited to Backbone. You can use React with any model library by subscribing to its changes in the lifecycle methods and, optionally, copying the data into the local React state.

JSX In Depth

Fundamentally, JSX just provides syntactic sugar for the React.createElement(component, props, ...children) function. The JSX code: <MyButton color="blue" shadowSize={2}> Click Me </MyButton> compiles into: React.createElement( MyButton, {color: 'blue', shadowSize: 2}, 'Click Me' ) You can also use the self-closing form of the tag if there are no children. So: <div className="sidebar" /> compiles into: React.createElement( 'div', {className: 'sidebar'} ) If you want to test out how some specific JSX is converted into JavaScript, you can try out the online Babel compiler.

Specifying The React Element Type

The first part of a JSX tag determines the type of the React element. Capitalized types indicate that the JSX tag is referring to a React component. These tags get compiled into a direct reference to the named variable, so if you use the JSX <Foo /> expression, Foo must be in scope.

React Must Be in Scope

Since JSX compiles into calls to React.createElement, the React library must also always be in scope from your JSX code. For example, both of the imports are necessary in this code, even though React and CustomButton are not directly referenced from JavaScript: import React from 'react';import CustomButton from './CustomButton'; function WarningButton() { // return React.createElement(CustomButton, {color: 'red'}, null); return <CustomButton color="red" />; } If you don't use a JavaScript bundler and loaded React from a <script> tag, it is already in scope as the React global.

Using Dot Notation for JSX Type

You can also refer to a React component using dot-notation from within JSX. This is convenient if you have a single module that exports many React components. For example, if MyComponents.DatePicker is a component, you can use it directly from JSX with: import React from 'react'; const MyComponents = { DatePicker: function DatePicker(props) { return <div>Imagine a {props.color} datepicker here.</div>; } } function BlueDatePicker() { return <MyComponents.DatePicker color="blue" />;}

User-Defined Components Must Be Capitalized

When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like <Foo /> compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file. We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX. For example, this code will not run as expected: import React from 'react'; // Wrong! This is a component and should have been capitalized:function hello(props) { // Correct! This use of <div> is legitimate because div is a valid HTML tag: return <div>Hello {props.toWhat}</div>; } function HelloWorld() { // Wrong! React thinks <hello /> is an HTML tag because it's not capitalized: return <hello toWhat="World" />;} To fix this, we will rename hello to Hello and use <Hello /> when referring to it: import React from 'react'; // Correct! This is a component and should be capitalized:function Hello(props) { // Correct! This use of <div> is legitimate because div is a valid HTML tag: return <div>Hello {props.toWhat}</div>; } function HelloWorld() { // Correct! React knows <Hello /> is a component because it's capitalized. return <Hello toWhat="World" />;}

Choosing the Type at Runtime

You cannot use a general expression as the React element type. If you do want to use a general expression to indicate the type of the element, just assign it to a capitalized variable first. This often comes up when you want to render a different component based on a prop: import React from 'react'; import { PhotoStory, VideoStory } from './stories'; const components = { photo: PhotoStory, video: VideoStory }; function Story(props) { // Wrong! JSX type can't be an expression. return <components[props.storyType] story={props.story} />;} To fix this, we will assign the type to a capitalized variable first: import React from 'react'; import { PhotoStory, VideoStory } from './stories'; const components = { photo: PhotoStory, video: VideoStory }; function Story(props) { // Correct! JSX type can be a capitalized variable. const SpecificStory = components[props.storyType]; return <SpecificStory story={props.story} />;}

Props in JSX

There are several different ways to specify props in JSX.

JavaScript Expressions as Props

You can pass any JavaScript expression as a prop, by surrounding it with {}. For example, in this JSX: <MyComponent foo={1 + 2 + 3 + 4} /> For MyComponent, the value of props.foo will be 10 because the expression 1 + 2 + 3 + 4 gets evaluated. if statements and for loops are not expressions in JavaScript, so they can't be used in JSX directly. Instead, you can put these in the surrounding code. For example: function NumberDescriber(props) { let description; if (props.number % 2 == 0) { description = <strong>even</strong>; } else { description = <i>odd</i>; } return <div>{props.number} is an {description} number</div>; } You can learn more about conditional rendering and loops in the corresponding sections.

String Literals

You can pass a string literal as a prop. These two JSX expressions are equivalent: <MyComponent message="hello world" /> <MyComponent message={'hello world'} /> When you pass a string literal, its value is HTML-unescaped. So these two JSX expressions are equivalent: <MyComponent message="&lt;3" /> <MyComponent message={'<3'} /> This behavior is usually not relevant. It's only mentioned here for completeness.

Props Default to ¡°True¡±

If you pass no value for a prop, it defaults to true. These two JSX expressions are equivalent: <MyTextBox autocomplete /> <MyTextBox autocomplete={true} /> In general, we don't recommend not passing a value for a prop, because it can be confused with the ES6 object shorthand {foo} which is short for {foo: foo} rather than {foo: true}. This behavior is just there so that it matches the behavior of HTML.

Spread Attributes

If you already have props as an object, and you want to pass it in JSX, you can use ... as a ¡°spread¡± operator to pass the whole props object. These two components are equivalent: function App1() { return <Greeting firstName="Ben" lastName="Hector" />; } function App2() { const props = {firstName: 'Ben', lastName: 'Hector'}; return <Greeting {...props} />;} You can also pick specific props that your component will consume while passing all other props using the spread operator. const Button = props => { const { kind, ...other } = props; const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton"; return <button className={className} {...other} />; }; const App = () => { return ( <div> <Button kind="primary" onClick={() => console.log("clicked!")}> Hello World! </Button> </div> ); }; In the example above, the kind prop is safely consumed and is not passed on to the <button> element in the DOM. All other props are passed via the ...other object making this component really flexible. You can see that it passes an onClick and children props. Spread attributes can be useful but they also make it easy to pass unnecessary props to components that don't care about them or to pass invalid HTML attributes to the DOM. We recommend using this syntax sparingly.

Children in JSX

In JSX expressions that contain both an opening tag and a closing tag, the content between those tags is passed as a special prop: props.children. There are several different ways to pass children:

String Literals

You can put a string between the opening and closing tags and props.children will just be that string. This is useful for many of the built-in HTML elements. For example: <MyComponent>Hello world!</MyComponent> This is valid JSX, and props.children in MyComponent will simply be the string "Hello world!". HTML is unescaped, so you can generally write JSX just like you would write HTML in this way: <div>This is valid HTML &amp; JSX at the same time.</div> JSX removes whitespace at the beginning and ending of a line. It also removes blank lines. New lines adjacent to tags are removed; new lines that occur in the middle of string literals are condensed into a single space. So these all render to the same thing: <div>Hello World</div> <div> Hello World </div> <div> Hello World </div> <div> Hello World </div>

JSX Children

You can provide more JSX elements as the children. This is useful for displaying nested components: <MyContainer> <MyFirstComponent /> <MySecondComponent /> </MyContainer> You can mix together different types of children, so you can use string literals together with JSX children. This is another way in which JSX is like HTML, so that this is both valid JSX and valid HTML: <div> Here is a list: <ul> <li>Item 1</li> <li>Item 2</li> </ul> </div> A React component can also return an array of elements: render() { // No need to wrap list items in an extra element! return [ // Don't forget the keys :) <li key="A">First item</li>, <li key="B">Second item</li>, <li key="C">Third item</li>, ]; }

JavaScript Expressions as Children

You can pass any JavaScript expression as children, by enclosing it within {}. For example, these expressions are equivalent: <MyComponent>foo</MyComponent> <MyComponent>{'foo'}</MyComponent> This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this renders an HTML list: function Item(props) { return <li>{props.message}</li>;} function TodoList() { const todos = ['finish doc', 'submit pr', 'nag dan to review']; return ( <ul> {todos.map((message) => <Item key={message} message={message} />)} </ul> ); } JavaScript expressions can be mixed with other types of children. This is often useful in lieu of string templates: function Hello(props) { return <div>Hello {props.addressee}!</div>;}

Functions as Children

Normally, JavaScript expressions inserted in JSX will evaluate to a string, a React element, or a list of those things. However, props.children works just like any other prop in that it can pass any sort of data, not just the sorts that React knows how to render. For example, if you have a custom component, you could have it take a callback as props.children: // Calls the children callback numTimes to produce a repeated component function Repeat(props) { let items = []; for (let i = 0; i < props.numTimes; i++) { items.push(props.children(i)); } return <div>{items}</div>; } function ListOfTenThings() { return ( <Repeat numTimes={10}> {(index) => <div key={index}>This is item {index} in the list</div>} </Repeat> ); } Children passed to a custom component can be anything, as long as that component transforms them into something React can understand before rendering. This usage is not common, but it works if you want to stretch what JSX is capable of.

Booleans, Null, and Undefined Are Ignored

false, null, undefined, and true are valid children. They simply don't render. These JSX expressions will all render to the same thing: <div /> <div></div> <div>{false}</div> <div>{null}</div> <div>{undefined}</div> <div>{true}</div> This can be useful to conditionally render React elements. This JSX renders the <Header /> component only if showHeader is true: <div> {showHeader && <Header />} <Content /> </div> One caveat is that some ¡°falsy¡± values, such as the 0 number, are still rendered by React. For example, this code will not behave as you might expect because 0 will be printed when props.messages is an empty array: <div> {props.messages.length && <MessageList messages={props.messages} /> } </div> To fix this, make sure that the expression before && is always boolean: <div> {props.messages.length > 0 && <MessageList messages={props.messages} /> } </div> Conversely, if you want a value like false, true, null, or undefined to appear in the output, you have to convert it to a string first: <div> My JavaScript variable is {String(myVariable)}.</div>

Optimizing Performance

Internally, React uses several clever techniques to minimize the number of costly DOM operations required to update the UI. For many applications, using React will lead to a fast user interface without doing much work to specifically optimize for performance. Nevertheless, there are several ways you can speed up your React application.

Use the Production Build

If you're benchmarking or experiencing performance problems in your React apps, make sure you're testing with the minified production build. By default, React includes many helpful warnings. These warnings are very useful in development. However, they make React larger and slower so you should make sure to use the production version when you deploy the app. If you aren't sure whether your build process is set up correctly, you can check it by installing React Developer Tools for Chrome. If you visit a site with React in production mode, the icon will have a dark background: If you visit a site with React in development mode, the icon will have a red background: It is expected that you use the development mode when working on your app, and the production mode when deploying your app to the users. You can find instructions for building your app for production below.

Create React App

If your project is built with Create React App, run: npm run build This will create a production build of your app in the build/ folder of your project. Remember that this is only necessary before deploying to production. For normal development, use npm start.

Single-File Builds

We offer production-ready versions of React and React DOM as single files: <script src="https://unpkg.com/react@17/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script> Remember that only React files ending with .production.min.js are suitable for production.

Brunch

For the most efficient Brunch production build, install the terser-brunch plugin: # If you use npm npm install --save-dev terser-brunch # If you use Yarn yarn add --dev terser-brunch Then, to create a production build, add the -p flag to the build command: brunch build -p Remember that you only need to do this for production builds. You shouldn't pass the -p flag or apply this plugin in development, because it will hide useful React warnings and make the builds much slower.

Browserify

For the most efficient Browserify production build, install a few plugins: # If you use npm npm install --save-dev envify terser uglifyify # If you use Yarn yarn add --dev envify terser uglifyify To create a production build, make sure that you add these transforms (the order matters):
  • The envify transform ensures the right build environment is set. Make it global (-g).
  • The uglifyify transform removes development imports. Make it global too (-g).
  • Finally, the resulting bundle is piped to terser for mangling (read why).
For example: browserify ./index.js \ -g [ envify --NODE_ENV production ] \ -g uglifyify \ | terser --compress --mangle > ./bundle.js Remember that you only need to do this for production builds. You shouldn't apply these plugins in development because they will hide useful React warnings, and make the builds much slower.

Rollup

For the most efficient Rollup production build, install a few plugins: # If you use npm npm install --save-dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser # If you use Yarn yarn add --dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser To create a production build, make sure that you add these plugins (the order matters):
  • The replace plugin ensures the right build environment is set.
  • The commonjs plugin provides support for CommonJS in Rollup.
  • The terser plugin compresses and mangles the final bundle.
plugins: [ // ... require('rollup-plugin-replace')({ 'process.env.NODE_ENV': JSON.stringify('production') }), require('rollup-plugin-commonjs')(), require('rollup-plugin-terser')(), // ... ] For a complete setup example see this gist. Remember that you only need to do this for production builds. You shouldn't apply the terser plugin or the replace plugin with 'production' value in development because they will hide useful React warnings, and make the builds much slower.

webpack

Note: If you're using Create React App, please follow the instructions above.
This section is only relevant if you configure webpack directly.
Webpack v4+ will minify your code by default in production mode. const TerserPlugin = require('terser-webpack-plugin'); module.exports = { mode: 'production', optimization: { minimizer: [new TerserPlugin({ /* additional options here */ })], }, }; You can learn more about this in webpack documentation. Remember that you only need to do this for production builds. You shouldn't apply TerserPlugin in development because it will hide useful React warnings, and make the builds much slower.

Profiling Components with the Chrome Performance Tab

In the development mode, you can visualize how components mount, update, and unmount, using the performance tools in supported browsers. For example: To do this in Chrome:
  1. Temporarily disable all Chrome extensions, especially React DevTools. They can significantly skew the results!
  2. Make sure you're running the application in the development mode.
  3. Open the Chrome DevTools Performance tab and press Record.
  4. Perform the actions you want to profile. Don't record more than 20 seconds or Chrome might hang.
  5. Stop recording.
  6. React events will be grouped under the User Timing label.
For a more detailed walkthrough, check out this article by Ben Schwarz. Note that the numbers are relative so components will render faster in production. Still, this should help you realize when unrelated UI gets updated by mistake, and how deep and how often your UI updates occur. Currently Chrome, Edge, and IE are the only browsers supporting this feature, but we use the standard User Timing API so we expect more browsers to add support for it.

Profiling Components with the DevTools Profiler

react-dom 16.5+ and react-native 0.57+ provide enhanced profiling capabilities in DEV mode with the React DevTools Profiler. An overview of the Profiler can be found in the blog post ¡°Introducing the React Profiler¡±. A video walkthrough of the profiler is also available on YouTube. If you haven't yet installed the React DevTools, you can find them here:
  • Chrome Browser Extension
  • Firefox Browser Extension
  • Standalone Node Package
Note A production profiling bundle of react-dom is also available as react-dom/profiling. Read more about how to use this bundle at fb.me/react-profiling

Virtualize Long Lists

If your application renders long lists of data (hundreds or thousands of rows), we recommended using a technique known as ¡°windowing¡±. This technique only renders a small subset of your rows at any given time, and can dramatically reduce the time it takes to re-render the components as well as the number of DOM nodes created. react-window and react-virtualized are popular windowing libraries. They provide several reusable components for displaying lists, grids, and tabular data. You can also create your own windowing component, like Twitter did, if you want something more tailored to your application's specific use case.

Avoid Reconciliation

React builds and maintains an internal representation of the rendered UI. It includes the React elements you return from your components. This representation lets React avoid creating DOM nodes and accessing existing ones beyond necessity, as that can be slower than operations on JavaScript objects. Sometimes it is referred to as a ¡°virtual DOM¡±, but it works the same way on React Native. When a component's props or state change, React decides whether an actual DOM update is necessary by comparing the newly returned element with the previously rendered one. When they are not equal, React will update the DOM. Even though React only updates the changed DOM nodes, re-rendering still takes some time. In many cases it's not a problem, but if the slowdown is noticeable, you can speed all of this up by overriding the lifecycle function shouldComponentUpdate, which is triggered before the re-rendering process starts. The default implementation of this function returns true, leaving React to perform the update: shouldComponentUpdate(nextProps, nextState) { return true; } If you know that in some situations your component doesn't need to update, you can return false from shouldComponentUpdate instead, to skip the whole rendering process, including calling render() on this component and below. In most cases, instead of writing shouldComponentUpdate() by hand, you can inherit from React.PureComponent. It is equivalent to implementing shouldComponentUpdate() with a shallow comparison of current and previous props and state.

shouldComponentUpdate In Action

Here's a subtree of components. For each one, SCU indicates what shouldComponentUpdate returned, and vDOMEq indicates whether the rendered React elements were equivalent. Finally, the circle's color indicates whether the component had to be reconciled or not. Since shouldComponentUpdate returned false for the subtree rooted at C2, React did not attempt to render C2, and thus didn't even have to invoke shouldComponentUpdate on C4 and C5. For C1 and C3, shouldComponentUpdate returned true, so React had to go down to the leaves and check them. For C6 shouldComponentUpdate returned true, and since the rendered elements weren't equivalent React had to update the DOM. The last interesting case is C8. React had to render this component, but since the React elements it returned were equal to the previously rendered ones, it didn't have to update the DOM. Note that React only had to do DOM mutations for C6, which was inevitable. For C8, it bailed out by comparing the rendered React elements, and for C2's subtree and C7, it didn't even have to compare the elements as we bailed out on shouldComponentUpdate, and render was not called.

Examples

If the only way your component ever changes is when the props.color or the state.count variable changes, you could have shouldComponentUpdate check that: class CounterButton extends React.Component { constructor(props) { super(props); this.state = {count: 1}; } shouldComponentUpdate(nextProps, nextState) { if (this.props.color !== nextProps.color) { return true; } if (this.state.count !== nextState.count) { return true; } return false; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); } } In this code, shouldComponentUpdate is just checking if there is any change in props.color or state.count. If those values don't change, the component doesn't update. If your component got more complex, you could use a similar pattern of doing a ¡°shallow comparison¡± between all the fields of props and state to determine if the component should update. This pattern is common enough that React provides a helper to use this logic - just inherit from React.PureComponent. So this code is a simpler way to achieve the same thing: class CounterButton extends React.PureComponent { constructor(props) { super(props); this.state = {count: 1}; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); } } Most of the time, you can use React.PureComponent instead of writing your own shouldComponentUpdate. It only does a shallow comparison, so you can't use it if the props or state may have been mutated in a way that a shallow comparison would miss. This can be a problem with more complex data structures. For example, let's say you want a ListOfWords component to render a comma-separated list of words, with a parent WordAdder component that lets you click a button to add a word to the list. This code does not work correctly: class ListOfWords extends React.PureComponent { render() { return <div>{this.props.words.join(',')}</div>; } } class WordAdder extends React.Component { constructor(props) { super(props); this.state = { words: ['marklar'] }; this.handleClick = this.handleClick.bind(this); } handleClick() { // This section is bad style and causes a bug const words = this.state.words; words.push('marklar'); this.setState({words: words}); } render() { return ( <div> <button onClick={this.handleClick} /> <ListOfWords words={this.state.words} /> </div> ); } } The problem is that PureComponent will do a simple comparison between the old and new values of this.props.words. Since this code mutates the words array in the handleClick method of WordAdder, the old and new values of this.props.words will compare as equal, even though the actual words in the array have changed. The ListOfWords will thus not update even though it has new words that should be rendered.

The Power Of Not Mutating Data

The simplest way to avoid this problem is to avoid mutating values that you are using as props or state. For example, the handleClick method above could be rewritten using concat as: handleClick() { this.setState(state => ({ words: state.words.concat(['marklar']) })); } ES6 supports a spread syntax for arrays which can make this easier. If you're using Create React App, this syntax is available by default. handleClick() { this.setState(state => ({ words: [...state.words, 'marklar'], })); }; You can also rewrite code that mutates objects to avoid mutation, in a similar way. For example, let's say we have an object named colormap and we want to write a function that changes colormap.right to be 'blue'. We could write: function updateColorMap(colormap) { colormap.right = 'blue'; } To write this without mutating the original object, we can use Object.assign method: function updateColorMap(colormap) { return Object.assign({}, colormap, {right: 'blue'}); } updateColorMap now returns a new object, rather than mutating the old one. Object.assign is in ES6 and requires a polyfill. Object spread syntax makes it easier to update objects without mutation as well: function updateColorMap(colormap) { return {...colormap, right: 'blue'}; } This feature was added to JavaScript in ES2018. If you're using Create React App, both Object.assign and the object spread syntax are available by default. When you deal with deeply nested objects, updating them in an immutable way can feel convoluted. If you run into this problem, check out Immer or immutability-helper. These libraries let you write highly readable code without losing the benefits of immutability.

Portals

Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. ReactDOM.createPortal(child, container) The first argument (child) is any renderable React child, such as an element, string, or fragment. The second argument (container) is a DOM element.

Usage

Normally, when you return an element from a component's render method, it's mounted into the DOM as a child of the nearest parent node: render() { // React mounts a new div and renders the children into it return ( <div> {this.props.children} </div> ); } However, sometimes it's useful to insert a child into a different location in the DOM: render() { // React does *not* create a new div. It renders the children into `domNode`. // `domNode` is any valid DOM node, regardless of its location in the DOM. return ReactDOM.createPortal( this.props.children, domNode ); } A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the child to visually ¡°break out¡± of its container. For example, dialogs, hovercards, and tooltips.
Note: When working with portals, remember that managing keyboard focus becomes very important. For modal dialogs, ensure that everyone can interact with them by following the WAI-ARIA Modal Authoring Practices.
Try it on CodePen

Event Bubbling Through Portals

Even though a portal can be anywhere in the DOM tree, it behaves like a normal React child in every other way. Features like context work exactly the same regardless of whether the child is a portal, as the portal still exists in the React tree regardless of position in the DOM tree. This includes event bubbling. An event fired from inside a portal will propagate to ancestors in the containing React tree, even if those elements are not ancestors in the DOM tree. Assuming the following HTML structure: <html> <body> <div id="app-root"></div> <div id="modal-root"></div> </body> </html> A Parent component in #app-root would be able to catch an uncaught, bubbling event from the sibling node #modal-root. // These two containers are siblings in the DOM const appRoot = document.getElementById('app-root'); const modalRoot = document.getElementById('modal-root'); class Modal extends React.Component { constructor(props) { super(props); this.el = document.createElement('div'); } componentDidMount() { // The portal element is inserted in the DOM tree after // the Modal's children are mounted, meaning that children // will be mounted on a detached DOM node. If a child // component requires to be attached to the DOM tree // immediately when mounted, for example to measure a // DOM node, or uses 'autoFocus' in a descendant, add // state to Modal and only render the children when Modal // is inserted in the DOM tree. modalRoot.appendChild(this.el); } componentWillUnmount() { modalRoot.removeChild(this.el); } render() { return ReactDOM.createPortal( this.props.children, this.el ); } } class Parent extends React.Component { constructor(props) { super(props); this.state = {clicks: 0}; this.handleClick = this.handleClick.bind(this); } handleClick() { // This will fire when the button in Child is clicked, // updating Parent's state, even though button // is not direct descendant in the DOM. this.setState(state => ({ clicks: state.clicks + 1 })); } render() { return ( <div onClick={this.handleClick}> <p>Number of clicks: {this.state.clicks}</p> <p> Open up the browser DevTools to observe that the button is not a child of the div with the onClick handler. </p> <Modal> <Child /> </Modal> </div> ); } } function Child() { // The click event on this button will bubble up to parent, // because there is no 'onClick' attribute defined return ( <div className="modal"> <button>Click</button> </div> ); } ReactDOM.render(<Parent />, appRoot); Try it on CodePen Catching an event bubbling up from a portal in a parent component allows the development of more flexible abstractions that are not inherently reliant on portals. For example, if you render a <Modal /> component, the parent can capture its events regardless of whether it's implemented using portals.

Profiler API

The Profiler measures how often a React application renders and what the ¡°cost¡± of rendering is. Its purpose is to help identify parts of an application that are slow and may benefit from optimizations such as memoization.
Note: Profiling adds some additional overhead, so it is disabled in the production build. To opt into production profiling, React provides a special production build with profiling enabled. Read more about how to use this build at fb.me/react-profiling

Usage

A Profiler can be added anywhere in a React tree to measure the cost of rendering that part of the tree. It requires two props: an id (string) and an onRender callback (function) which React calls any time a component within the tree ¡°commits¡± an update. For example, to profile a Navigation component and its descendants: render( <App> <Profiler id="Navigation" onRender={callback}> <Navigation {...props} /> </Profiler> <Main {...props} /> </App> ); Multiple Profiler components can be used to measure different parts of an application: render( <App> <Profiler id="Navigation" onRender={callback}> <Navigation {...props} /> </Profiler> <Profiler id="Main" onRender={callback}> <Main {...props} /> </Profiler> </App> ); Profiler components can also be nested to measure different components within the same subtree: render( <App> <Profiler id="Panel" onRender={callback}> <Panel {...props}> <Profiler id="Content" onRender={callback}> <Content {...props} /> </Profiler> <Profiler id="PreviewPane" onRender={callback}> <PreviewPane {...props} /> </Profiler> </Panel> </Profiler> </App> );
Note Although Profiler is a light-weight component, it should be used only when necessary; each use adds some CPU and memory overhead to an application.

onRender Callback

The Profiler requires an onRender function as a prop. React calls this function any time a component within the profiled tree ¡°commits¡± an update. It receives parameters describing what was rendered and how long it took. function onRenderCallback( id, // the "id" prop of the Profiler tree that has just committed phase, // either "mount" (if the tree just mounted) or "update" (if it re-rendered) actualDuration, // time spent rendering the committed update baseDuration, // estimated time to render the entire subtree without memoization startTime, // when React began rendering this update commitTime, // when React committed this update interactions // the Set of interactions belonging to this update ) { // Aggregate or log render timings... } Let's take a closer look at each of the props:
  • id: string - The id prop of the Profiler tree that has just committed. This can be used to identify which part of the tree was committed if you are using multiple profilers.
  • phase: "mount" | "update" - Identifies whether the tree has just been mounted for the first time or re-rendered due to a change in props, state, or hooks.
  • actualDuration: number - Time spent rendering the Profiler and its descendants for the current update. This indicates how well the subtree makes use of memoization (e.g. React.memo, useMemo, shouldComponentUpdate). Ideally this value should decrease significantly after the initial mount as many of the descendants will only need to re-render if their specific props change.
  • baseDuration: number - Duration of the most recent render time for each individual component within the Profiler tree. This value estimates a worst-case cost of rendering (e.g. the initial mount or a tree with no memoization).
  • startTime: number - Timestamp when React began rendering the current update.
  • commitTime: number - Timestamp when React committed the current update. This value is shared between all profilers in a commit, enabling them to be grouped if desirable.
  • interactions: Set - Set of ¡°interactions¡± that were being traced when the update was scheduled (e.g. when render or setState were called).
Note Interactions can be used to identify the cause of an update, although the API for tracing them is still experimental. Learn more about it at fb.me/react-interaction-tracing

React Without ES6

Normally you would define a React component as a plain JavaScript class: class Greeting extends React.Component { render() { return <h2>Hello, {this.props.name}</h2>; } } If you don't use ES6 yet, you may use the create-react-class module instead: var createReactClass = require('create-react-class'); var Greeting = createReactClass({ render: function() { return <h2>Hello, {this.props.name}</h2>; } }); The API of ES6 classes is similar to createReactClass() with a few exceptions.

Declaring Default Props

With functions and ES6 classes defaultProps is defined as a property on the component itself: class Greeting extends React.Component { // ... } Greeting.defaultProps = { name: 'Mary' }; With createReactClass(), you need to define getDefaultProps() as a function on the passed object: var Greeting = createReactClass({ getDefaultProps: function() { return { name: 'Mary' }; }, // ... });

Setting the Initial State

In ES6 classes, you can define the initial state by assigning this.state in the constructor: class Counter extends React.Component { constructor(props) { super(props); this.state = {count: props.initialCount}; } // ... } With createReactClass(), you have to provide a separate getInitialState method that returns the initial state: var Counter = createReactClass({ getInitialState: function() { return {count: this.props.initialCount}; }, // ... });

Autobinding

In React components declared as ES6 classes, methods follow the same semantics as regular ES6 classes. This means that they don't automatically bind this to the instance. You'll have to explicitly use .bind(this) in the constructor: class SayHello extends React.Component { constructor(props) { super(props); this.state = {message: 'Hello!'}; // This line is important! this.handleClick = this.handleClick.bind(this); } handleClick() { alert(this.state.message); } render() { // Because `this.handleClick` is bound, we can use it as an event handler. return ( <button onClick={this.handleClick}> Say hello </button> ); } } With createReactClass(), this is not necessary because it binds all methods: var SayHello = createReactClass({ getInitialState: function() { return {message: 'Hello!'}; }, handleClick: function() { alert(this.state.message); }, render: function() { return ( <button onClick={this.handleClick}> Say hello </button> ); } }); This means writing ES6 classes comes with a little more boilerplate code for event handlers, but the upside is slightly better performance in large applications. If the boilerplate code is too unattractive to you, you may enable the experimental Class Properties syntax proposal with Babel: class SayHello extends React.Component { constructor(props) { super(props); this.state = {message: 'Hello!'}; } // WARNING: this syntax is experimental! // Using an arrow here binds the method: handleClick = () => { alert(this.state.message); } render() { return ( <button onClick={this.handleClick}> Say hello </button> ); } } Please note that the syntax above is experimental and the syntax may change, or the proposal might not make it into the language. If you'd rather play it safe, you have a few options:
  • Bind methods in the constructor.
  • Use arrow functions, e.g. onClick={(e) => this.handleClick(e)}.
  • Keep using createReactClass.

Mixins

Note: ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes. We also found numerous issues in codebases using mixins, and don't recommend using them in the new code. This section exists only for the reference.
Sometimes very different components may share some common functionality. These are sometimes called cross-cutting concerns. createReactClass lets you use a legacy mixins system for that. One common use case is a component wanting to update itself on a time interval. It's easy to use setInterval(), but it's important to cancel your interval when you don't need it anymore to save memory. React provides lifecycle methods that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy setInterval() function that will automatically get cleaned up when your component is destroyed. var SetIntervalMixin = { componentWillMount: function() { this.intervals = []; }, setInterval: function() { this.intervals.push(setInterval.apply(null, arguments)); }, componentWillUnmount: function() { this.intervals.forEach(clearInterval); } }; var createReactClass = require('create-react-class'); var TickTock = createReactClass({ mixins: [SetIntervalMixin], // Use the mixin getInitialState: function() { return {seconds: 0}; }, componentDidMount: function() { this.setInterval(this.tick, 1000); // Call a method on the mixin }, tick: function() { this.setState({seconds: this.state.seconds + 1}); }, render: function() { return ( <p> React has been running for {this.state.seconds} seconds. </p> ); } }); ReactDOM.render( <TickTock />, document.getElementById('example') ); If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.

React Without JSX

JSX is not a requirement for using React. Using React without JSX is especially convenient when you don't want to set up compilation in your build environment. Each JSX element is just syntactic sugar for calling React.createElement(component, props, ...children). So, anything you can do with JSX can also be done with just plain JavaScript. For example, this code written with JSX: class Hello extends React.Component { render() { return <div>Hello {this.props.toWhat}</div>; } } ReactDOM.render( <Hello toWhat="World" />, document.getElementById('root') ); can be compiled to this code that does not use JSX: class Hello extends React.Component { render() { return React.createElement('div', null, `Hello ${this.props.toWhat}`); } } ReactDOM.render( React.createElement(Hello, {toWhat: 'World'}, null), document.getElementById('root') ); If you're curious to see more examples of how JSX is converted to JavaScript, you can try out the online Babel compiler. The component can either be provided as a string, as a subclass of React.Component, or a plain function. If you get tired of typing React.createElement so much, one common pattern is to assign a shorthand: const e = React.createElement; ReactDOM.render( e('div', null, 'Hello World'), document.getElementById('root') ); If you use this shorthand form for React.createElement, it can be almost as convenient to use React without JSX. Alternatively, you can refer to community projects such as react-hyperscript and hyperscript-helpers which offer a terser syntax.

Reconciliation

React provides a declarative API so that you don't have to worry about exactly what changes on every update. This makes writing applications a lot easier, but it might not be obvious how this is implemented within React. This article explains the choices we made in React's ¡°diffing¡± algorithm so that component updates are predictable while being fast enough for high-performance apps.

Motivation

When you use React, at a single point in time you can think of the render() function as creating a tree of React elements. On the next state or props update, that render() function will return a different tree of React elements. React then needs to figure out how to efficiently update the UI to match the most recent tree. There are some generic solutions to this algorithmic problem of generating the minimum number of operations to transform one tree into another. However, the state of the art algorithms have a complexity in the order of O(n3) where n is the number of elements in the tree. If we used this in React, displaying 1000 elements would require in the order of one billion comparisons. This is far too expensive. Instead, React implements a heuristic O(n) algorithm based on two assumptions:
  1. Two elements of different types will produce different trees.
  2. The developer can hint at which child elements may be stable across different renders with a key prop.
In practice, these assumptions are valid for almost all practical use cases.

The Diffing Algorithm

When diffing two trees, React first compares the two root elements. The behavior is different depending on the types of the root elements.

Elements Of Different Types

Whenever the root elements have different types, React will tear down the old tree and build the new tree from scratch. Going from <a> to <img>, or from <Article> to <Comment>, or from <Button> to <div> - any of those will lead to a full rebuild. When tearing down a tree, old DOM nodes are destroyed. Component instances receive componentWillUnmount(). When building up a new tree, new DOM nodes are inserted into the DOM. Component instances receive UNSAFE_componentWillMount() and then componentDidMount(). Any state associated with the old tree is lost. Any components below the root will also get unmounted and have their state destroyed. For example, when diffing: <div> <Counter /> </div> <span> <Counter /> </span> This will destroy the old Counter and remount a new one.
Note: These methods are considered legacy and you should avoid them in new code:
  • UNSAFE_componentWillMount()

DOM Elements Of The Same Type

When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes. For example: <div className="before" title="stuff" /> <div className="after" title="stuff" /> By comparing these two elements, React knows to only modify the className on the underlying DOM node. When updating style, React also knows to update only the properties that changed. For example: <div style={{color: 'red', fontWeight: 'bold'}} /> <div style={{color: 'green', fontWeight: 'bold'}} /> When converting between these two elements, React knows to only modify the color style, not the fontWeight. After handling the DOM node, React then recurses on the children.

Component Elements Of The Same Type

When a component updates, the instance stays the same, so that state is maintained across renders. React updates the props of the underlying component instance to match the new element, and calls UNSAFE_componentWillReceiveProps(), UNSAFE_componentWillUpdate() and componentDidUpdate() on the underlying instance. Next, the render() method is called and the diff algorithm recurses on the previous result and the new result.
Note: These methods are considered legacy and you should avoid them in new code:
  • UNSAFE_componentWillUpdate()
  • UNSAFE_componentWillReceiveProps()

Recursing On Children

By default, when recursing on the children of a DOM node, React just iterates over both lists of children at the same time and generates a mutation whenever there's a difference. For example, when adding an element at the end of the children, converting between these two trees works well: <ul> <li>first</li> <li>second</li> </ul> <ul> <li>first</li> <li>second</li> <li>third</li> </ul> React will match the two <li>first</li> trees, match the two <li>second</li> trees, and then insert the <li>third</li> tree. If you implement it naively, inserting an element at the beginning has worse performance. For example, converting between these two trees works poorly: <ul> <li>Duke</li> <li>Villanova</li> </ul> <ul> <li>Connecticut</li> <li>Duke</li> <li>Villanova</li> </ul> React will mutate every child instead of realizing it can keep the <li>Duke</li> and <li>Villanova</li> subtrees intact. This inefficiency can be a problem.

Keys

In order to solve this issue, React supports a key attribute. When children have keys, React uses the key to match children in the original tree with children in the subsequent tree. For example, adding a key to our inefficient example above can make the tree conversion efficient: <ul> <li key="2015">Duke</li> <li key="2016">Villanova</li> </ul> <ul> <li key="2014">Connecticut</li> <li key="2015">Duke</li> <li key="2016">Villanova</li> </ul> Now React knows that the element with key '2014' is the new one, and the elements with the keys '2015' and '2016' have just moved. In practice, finding a key is usually not hard. The element you are going to display may already have a unique ID, so the key can just come from your data: <li key={item.id}>{item.name}</li> When that's not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. The key only has to be unique among its siblings, not globally unique. As a last resort, you can pass an item's index in the array as a key. This can work well if the items are never reordered, but reorders will be slow. Reorders can also cause issues with component state when indexes are used as keys. Component instances are updated and reused based on their key. If the key is an index, moving an item changes it. As a result, component state for things like uncontrolled inputs can get mixed up and updated in unexpected ways. Here is an example of the issues that can be caused by using indexes as keys on CodePen, and here is an updated version of the same example showing how not using indexes as keys will fix these reordering, sorting, and prepending issues.

Tradeoffs

It is important to remember that the reconciliation algorithm is an implementation detail. React could rerender the whole app on every action; the end result would be the same. Just to be clear, rerender in this context means calling render for all components, it doesn't mean React will unmount and remount them. It will only apply the differences following the rules stated in the previous sections. We are regularly refining the heuristics in order to make common use cases faster. In the current implementation, you can express the fact that a subtree has been moved amongst its siblings, but you cannot tell that it has moved somewhere else. The algorithm will rerender that full subtree. Because React relies on heuristics, if the assumptions behind them are not met, performance will suffer.
  1. The algorithm will not try to match subtrees of different component types. If you see yourself alternating between two component types with very similar output, you may want to make it the same type. In practice, we haven't found this to be an issue.
  2. Keys should be stable, predictable, and unique. Unstable keys (like those produced by Math.random()) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.

Refs and the DOM

Refs provide a way to access DOM nodes or React elements created in the render method. In the typical React dataflow, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props. However, there are a few cases where you need to imperatively modify a child outside of the typical dataflow. The child to be modified could be an instance of a React component, or it could be a DOM element. For both of these cases, React provides an escape hatch.

When to Use Refs

There are a few good use cases for refs:
  • Managing focus, text selection, or media playback.
  • Triggering imperative animations.
  • Integrating with third-party DOM libraries.
Avoid using refs for anything that can be done declaratively. For example, instead of exposing open() and close() methods on a Dialog component, pass an isOpen prop to it.

Don't Overuse Refs

Your first inclination may be to use refs to ¡°make things happen¡± in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to ¡°own¡± that state is at a higher level in the hierarchy. See the Lifting State Up guide for examples of this.
Note The examples below have been updated to use the React.createRef() API introduced in React 16.3. If you are using an earlier release of React, we recommend using callback refs instead.

Creating Refs

Refs are created using React.createRef() and attached to React elements via the ref attribute. Refs are commonly assigned to an instance property when a component is constructed so they can be referenced throughout the component. class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return <div ref={this.myRef} />; } }

Accessing Refs

When a ref is passed to an element in render, a reference to the node becomes accessible at the current attribute of the ref. const node = this.myRef.current; The value of the ref differs depending on the type of the node:
  • When the ref attribute is used on an HTML element, the ref created in the constructor with React.createRef() receives the underlying DOM element as its current property.
  • When the ref attribute is used on a custom class component, the ref object receives the mounted instance of the component as its current.
  • You may not use the ref attribute on function components because they don't have instances.
The examples below demonstrate the differences.
Adding a Ref to a DOM Element
This code uses a ref to store a reference to a DOM node: class CustomTextInput extends React.Component { constructor(props) { super(props); // create a ref to store the textInput DOM element this.textInput = React.createRef(); this.focusTextInput = this.focusTextInput.bind(this); } focusTextInput() { // Explicitly focus the text input using the raw DOM API // Note: we're accessing "current" to get the DOM node this.textInput.current.focus(); } render() { // tell React that we want to associate the <input> ref // with the `textInput` that we created in the constructor return ( <div> <input type="text" ref={this.textInput} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } } React will assign the current property with the DOM element when the component mounts, and assign it back to null when it unmounts. ref updates happen before componentDidMount or componentDidUpdate lifecycle methods.
Adding a Ref to a Class Component
If we wanted to wrap the CustomTextInput above to simulate it being clicked immediately after mounting, we could use a ref to get access to the custom input and call its focusTextInput method manually: class AutoFocusTextInput extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } componentDidMount() { this.textInput.current.focusTextInput(); } render() { return ( <CustomTextInput ref={this.textInput} /> ); } } Note that this only works if CustomTextInput is declared as a class: class CustomTextInput extends React.Component { // ... }
Refs and Function Components
By default, you may not use the ref attribute on function components because they don't have instances: function MyFunctionComponent() { return <input />; } class Parent extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } render() { // This will *not* work! return ( <MyFunctionComponent ref={this.textInput} /> ); } } If you want to allow people to take a ref to your function component, you can use forwardRef (possibly in conjunction with useImperativeHandle), or you can convert the component to a class. You can, however, use the ref attribute inside a function component as long as you refer to a DOM element or a class component: function CustomTextInput(props) { // textInput must be declared here so the ref can refer to it const textInput = useRef(null); function handleClick() { textInput.current.focus(); } return ( <div> <input type="text" ref={textInput} /> <input type="button" value="Focus the text input" onClick={handleClick} /> </div> ); }

Exposing DOM Refs to Parent Components

In rare cases, you might want to have access to a child's DOM node from a parent component. This is generally not recommended because it breaks component encapsulation, but it can occasionally be useful for triggering focus or measuring the size or position of a child DOM node. While you could add a ref to the child component, this is not an ideal solution, as you would only get a component instance rather than a DOM node. Additionally, this wouldn't work with function components. If you use React 16.3 or higher, we recommend to use ref forwarding for these cases. Ref forwarding lets components opt into exposing any child component's ref as their own. You can find a detailed example of how to expose a child's DOM node to a parent component in the ref forwarding documentation. If you use React 16.2 or lower, or if you need more flexibility than provided by ref forwarding, you can use this alternative approach and explicitly pass a ref as a differently named prop. When possible, we advise against exposing DOM nodes, but it can be a useful escape hatch. Note that this approach requires you to add some code to the child component. If you have absolutely no control over the child component implementation, your last option is to use findDOMNode(), but it is discouraged and deprecated in StrictMode.

Callback Refs

React also supports another way to set refs called ¡°callback refs¡±, which gives more fine-grain control over when refs are set and unset. Instead of passing a ref attribute created by createRef(), you pass a function. The function receives the React component instance or HTML DOM element as its argument, which can be stored and accessed elsewhere. The example below implements a common pattern: using the ref callback to store a reference to a DOM node in an instance property. class CustomTextInput extends React.Component { constructor(props) { super(props); this.textInput = null; this.setTextInputRef = element => { this.textInput = element; }; this.focusTextInput = () => { // Focus the text input using the raw DOM API if (this.textInput) this.textInput.focus(); }; } componentDidMount() { // autofocus the input on mount this.focusTextInput(); } render() { // Use the `ref` callback to store a reference to the text input DOM // element in an instance field (for example, this.textInput). return ( <div> <input type="text" ref={this.setTextInputRef} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } } React will call the ref callback with the DOM element when the component mounts, and call it with null when it unmounts. Refs are guaranteed to be up-to-date before componentDidMount or componentDidUpdate fires. You can pass callback refs between components like you can with object refs that were created with React.createRef(). function CustomTextInput(props) { return ( <div> <input ref={props.inputRef} /> </div> ); } class Parent extends React.Component { render() { return ( <CustomTextInput inputRef={el => this.inputElement = el} /> ); } } In the example above, Parent passes its ref callback as an inputRef prop to the CustomTextInput, and the CustomTextInput passes the same function as a special ref attribute to the <input>. As a result, this.inputElement in Parent will be set to the DOM node corresponding to the <input> element in the CustomTextInput.

Legacy API: String Refs

If you worked with React before, you might be familiar with an older API where the ref attribute is a string, like "textInput", and the DOM node is accessed as this.refs.textInput. We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases.
Note If you're currently using this.refs.textInput to access refs, we recommend using either the callback pattern or the createRef API instead.

Caveats with callback refs

If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the ref callback as a bound method on the class, but note that it shouldn't matter in most cases.

Render Props

The term ¡°render prop¡± refers to a technique for sharing code between React components using a prop whose value is a function. A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic. <DataProvider render={data => ( <h2>Hello {data.target}</h2> )}/> Libraries that use render props include React Router, Downshift and Formik. In this document, we'll discuss why render props are useful, and how to write your own.

Use Render Props for Cross-Cutting Concerns

Components are the primary unit of code reuse in React, but it's not always obvious how to share the state or behavior that one component encapsulates to other components that need that same state. For example, the following component tracks the mouse position in a web app: class MouseTracker extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; } handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); } render() { return ( <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}> <h2>Move the mouse around!</h2> <p>The current mouse position is ({this.state.x}, {this.state.y})</p> </div> ); } } As the cursor moves around the screen, the component displays its (x, y) coordinates in a <p>. Now the question is: How can we reuse this behavior in another component? In other words, if another component needs to know about the cursor position, can we encapsulate that behavior so that we can easily share it with that component? Since components are the basic unit of code reuse in React, let's try refactoring the code a bit to use a <Mouse> component that encapsulates the behavior we need to reuse elsewhere. // The <Mouse> component encapsulates the behavior we need... class Mouse extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; } handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); } render() { return ( <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}> {/* ...but how do we render something other than a <p>? */} <p>The current mouse position is ({this.state.x}, {this.state.y})</p> </div> ); } } class MouseTracker extends React.Component { render() { return ( <> <h2>Move the mouse around!</h2> <Mouse /> </> ); } } Now the <Mouse> component encapsulates all behavior associated with listening for mousemove events and storing the (x, y) position of the cursor, but it's not yet truly reusable. For example, let's say we have a <Cat> component that renders the image of a cat chasing the mouse around the screen. We might use a <Cat mouse={{ x, y }}> prop to tell the component the coordinates of the mouse so it knows where to position the image on the screen. As a first pass, you might try rendering the <Cat> inside <Mouse>'s render method, like this: class Cat extends React.Component { render() { const mouse = this.props.mouse; return ( <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} /> ); } } class MouseWithCat extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; } handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); } render() { return ( <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}> {/* We could just swap out the <p> for a <Cat> here ... but then we would need to create a separate <MouseWithSomethingElse> component every time we need to use it, so <MouseWithCat> isn't really reusable yet. */} <Cat mouse={this.state} /> </div> ); } } class MouseTracker extends React.Component { render() { return ( <div> <h2>Move the mouse around!</h2> <MouseWithCat /> </div> ); } } This approach will work for our specific use case, but we haven't achieved the objective of truly encapsulating the behavior in a reusable way. Now, every time we want the mouse position for a different use case, we have to create a new component (i.e. essentially another <MouseWithCat>) that renders something specifically for that use case. Here's where the render prop comes in: Instead of hard-coding a <Cat> inside a <Mouse> component, and effectively changing its rendered output, we can provide <Mouse> with a function prop that it uses to dynamically determine what to render¨Ca render prop. class Cat extends React.Component { render() { const mouse = this.props.mouse; return ( <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} /> ); } } class Mouse extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; } handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); } render() { return ( <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}> {/* Instead of providing a static representation of what <Mouse> renders, use the `render` prop to dynamically determine what to render. */} {this.props.render(this.state)} </div> ); } } class MouseTracker extends React.Component { render() { return ( <div> <h2>Move the mouse around!</h2> <Mouse render={mouse => ( <Cat mouse={mouse} /> )}/> </div> ); } } Now, instead of effectively cloning the <Mouse> component and hard-coding something else in its render method to solve for a specific use case, we provide a render prop that <Mouse> can use to dynamically determine what it renders. More concretely, a render prop is a function prop that a component uses to know what to render. This technique makes the behavior that we need to share extremely portable. To get that behavior, render a <Mouse> with a render prop that tells it what to render with the current (x, y) of the cursor. One interesting thing to note about render props is that you can implement most higher-order components (HOC) using a regular component with a render prop. For example, if you would prefer to have a withMouse HOC instead of a <Mouse> component, you could easily create one using a regular <Mouse> with a render prop: // If you really want a HOC for some reason, you can easily // create one using a regular component with a render prop! function withMouse(Component) { return class extends React.Component { render() { return ( <Mouse render={mouse => ( <Component {...this.props} mouse={mouse} /> )}/> ); } } } So using a render prop makes it possible to use either pattern.

Using Props Other Than render

It's important to remember that just because the pattern is called ¡°render props¡± you don't have to use a prop named render to use this pattern. In fact, any prop that is a function that a component uses to know what to render is technically a ¡°render prop¡±. Although the examples above use render, we could just as easily use the children prop! <Mouse children={mouse => ( <p>The mouse position is {mouse.x}, {mouse.y}</p> )}/> And remember, the children prop doesn't actually need to be named in the list of ¡°attributes¡± in your JSX element. Instead, you can put it directly inside the element! <Mouse> {mouse => ( <p>The mouse position is {mouse.x}, {mouse.y}</p> )} </Mouse> You'll see this technique used in the react-motion API. Since this technique is a little unusual, you'll probably want to explicitly state that children should be a function in your propTypes when designing an API like this. Mouse.propTypes = { children: PropTypes.func.isRequired };

Caveats

Be careful when using Render Props with React.PureComponent

Using a render prop can negate the advantage that comes from using React.PureComponent if you create the function inside a render method. This is because the shallow prop comparison will always return false for new props, and each render in this case will generate a new value for the render prop. For example, continuing with our <Mouse> component from above, if Mouse were to extend React.PureComponent instead of React.Component, our example would look like this: class Mouse extends React.PureComponent { // Same implementation as above... } class MouseTracker extends React.Component { render() { return ( <div> <h2>Move the mouse around!</h2> {/* This is bad! The value of the `render` prop will be different on each render. */} <Mouse render={mouse => ( <Cat mouse={mouse} /> )}/> </div> ); } } In this example, each time <MouseTracker> renders, it generates a new function as the value of the <Mouse render> prop, thus negating the effect of <Mouse> extending React.PureComponent in the first place! To get around this problem, you can sometimes define the prop as an instance method, like so: class MouseTracker extends React.Component { // Defined as an instance method, `this.renderTheCat` always // refers to *same* function when we use it in render renderTheCat(mouse) { return <Cat mouse={mouse} />; } render() { return ( <div> <h2>Move the mouse around!</h2> <Mouse render={this.renderTheCat} /> </div> ); } } In cases where you cannot define the prop statically (e.g. because you need to close over the component's props and/or state) <Mouse> should extend React.Component instead.

Static Type Checking

Static type checkers like Flow and TypeScript identify certain types of problems before you even run your code. They can also improve developer workflow by adding features like auto-completion. For this reason, we recommend using Flow or TypeScript instead of PropTypes for larger code bases.

Flow

Flow is a static type checker for your JavaScript code. It is developed at Facebook and is often used with React. It lets you annotate the variables, functions, and React components with a special type syntax, and catch mistakes early. You can read an introduction to Flow to learn its basics. To use Flow, you need to:
  • Add Flow to your project as a dependency.
  • Ensure that Flow syntax is stripped from the compiled code.
  • Add type annotations and run Flow to check them.
We will explain these steps below in detail.

Adding Flow to a Project

First, navigate to your project directory in the terminal. You will need to run the following command: If you use Yarn, run: yarn add --dev flow-bin If you use npm, run: npm install --save-dev flow-bin This command installs the latest version of Flow into your project. Now, add flow to the "scripts" section of your package.json to be able to use this from the terminal: { // ... "scripts": { "flow": "flow", // ... }, // ... } Finally, run one of the following commands: If you use Yarn, run: yarn run flow init If you use npm, run: npm run flow init This command will create a Flow configuration file that you will need to commit.

Stripping Flow Syntax from the Compiled Code

Flow extends the JavaScript language with a special syntax for type annotations. However, browsers aren't aware of this syntax, so we need to make sure it doesn't end up in the compiled JavaScript bundle that is sent to the browser. The exact way to do this depends on the tools you use to compile JavaScript.
Create React App
If your project was set up using Create React App, congratulations! The Flow annotations are already being stripped by default so you don't need to do anything else in this step.
Babel
Note: These instructions are not for Create React App users. Even though Create React App uses Babel under the hood, it is already configured to understand Flow. Only follow this step if you don't use Create React App.
If you manually configured Babel for your project, you will need to install a special preset for Flow. If you use Yarn, run: yarn add --dev @babel/preset-flow If you use npm, run: npm install --save-dev @babel/preset-flow Then add the flow preset to your Babel configuration. For example, if you configure Babel through .babelrc file, it could look like this: { "presets": [ "@babel/preset-flow", "react" ] } This will let you use the Flow syntax in your code.
Note: Flow does not require the react preset, but they are often used together. Flow itself understands JSX syntax out of the box.
Other Build Setups
If you don't use either Create React App or Babel, you can use flow-remove-types to strip the type annotations.

Running Flow

If you followed the instructions above, you should be able to run Flow for the first time. yarn flow If you use npm, run: npm run flow You should see a message like: No errors! Done in 0.17s.

Adding Flow Type Annotations

By default, Flow only checks the files that include this annotation: // @flow Typically it is placed at the top of a file. Try adding it to some files in your project and run yarn flow or npm run flow to see if Flow already found any issues. There is also an option to force Flow to check all files regardless of the annotation. This can be too noisy for existing projects, but is reasonable for a new project if you want to fully type it with Flow. Now you're all set! We recommend to check out the following resources to learn more about Flow:
  • Flow Documentation: Type Annotations
  • Flow Documentation: Editors
  • Flow Documentation: React
  • Linting in Flow

TypeScript

TypeScript is a programming language developed by Microsoft. It is a typed superset of JavaScript, and includes its own compiler. Being a typed language, TypeScript can catch errors and bugs at build time, long before your app goes live. You can learn more about using TypeScript with React here. To use TypeScript, you need to:
  • Add TypeScript as a dependency to your project
  • Configure the TypeScript compiler options
  • Use the right file extensions
  • Add definitions for libraries you use
Let's go over these in detail.

Using TypeScript with Create React App

Create React App supports TypeScript out of the box. To create a new project with TypeScript support, run: npx create-react-app my-app --template typescript You can also add it to an existing Create React App project, as documented here.
Note: If you use Create React App, you can skip the rest of this page. It describes the manual setup which doesn't apply to Create React App users.

Adding TypeScript to a Project

It all begins with running one command in your terminal. If you use Yarn, run: yarn add --dev typescript If you use npm, run: npm install --save-dev typescript Congrats! You've installed the latest version of TypeScript into your project. Installing TypeScript gives us access to the tsc command. Before configuration, let's add tsc to the ¡°scripts¡± section in our package.json: { // ... "scripts": { "build": "tsc", // ... }, // ... }

Configuring the TypeScript Compiler

The compiler is of no help to us until we tell it what to do. In TypeScript, these rules are defined in a special file called tsconfig.json. To generate this file: If you use Yarn, run: yarn run tsc --init If you use npm, run: npx tsc --init Looking at the now generated tsconfig.json, you can see that there are many options you can use to configure the compiler. For a detailed description of all the options, check here. Of the many options, we'll look at rootDir and outDir. In its true fashion, the compiler will take in typescript files and generate javascript files. However we don't want to get confused with our source files and the generated output. We'll address this in two steps:
  • Firstly, let's arrange our project structure like this. We'll place all our source code in the src directory.
©À©¤©¤ package.json ©À©¤©¤ src ©¦ ©¸©¤©¤ index.ts ©¸©¤©¤ tsconfig.json
  • Next, we'll tell the compiler where our source code is and where the output should go.
// tsconfig.json { "compilerOptions": { // ... "rootDir": "src", "outDir": "build" // ... }, } Great! Now when we run our build script the compiler will output the generated javascript to the build folder. The TypeScript React Starter provides a tsconfig.json with a good set of rules to get you started. Generally, you don't want to keep the generated javascript in your source control, so be sure to add the build folder to your .gitignore.

File extensions

In React, you most likely write your components in a .js file. In TypeScript we have 2 file extensions: .ts is the default file extension while .tsx is a special extension used for files which contain JSX.

Running TypeScript

If you followed the instructions above, you should be able to run TypeScript for the first time. yarn build If you use npm, run: npm run build If you see no output, it means that it completed successfully.

Type Definitions

To be able to show errors and hints from other packages, the compiler relies on declaration files. A declaration file provides all the type information about a library. This enables us to use javascript libraries like those on npm in our project. There are two main ways to get declarations for a library: Bundled - The library bundles its own declaration file. This is great for us, since all we need to do is install the library, and we can use it right away. To check if a library has bundled types, look for an index.d.ts file in the project. Some libraries will have it specified in their package.json under the typings or types field. DefinitelyTyped - DefinitelyTyped is a huge repository of declarations for libraries that don't bundle a declaration file. The declarations are crowd-sourced and managed by Microsoft and open source contributors. React for example doesn't bundle its own declaration file. Instead we can get it from DefinitelyTyped. To do so enter this command in your terminal. # yarn yarn add --dev @types/react # npm npm i --save-dev @types/react Local Declarations Sometimes the package that you want to use doesn't bundle declarations nor is it available on DefinitelyTyped. In that case, we can have a local declaration file. To do this, create a declarations.d.ts file in the root of your source directory. A simple declaration could look like this: declare module 'querystring' { export function stringify(val: object): string export function parse(val: string): object } You are now ready to code! We recommend to check out the following resources to learn more about TypeScript:
  • TypeScript Documentation: Basic Types
  • TypeScript Documentation: Migrating from Javascript
  • TypeScript Documentation: React and Webpack

Reason

Reason is not a new language; it's a new syntax and toolchain powered by the battle-tested language, OCaml. Reason gives OCaml a familiar syntax geared toward JavaScript programmers, and caters to the existing NPM/Yarn workflow folks already know. Reason is developed at Facebook, and is used in some of its products like Messenger. It is still somewhat experimental but it has dedicated React bindings maintained by Facebook and a vibrant community.

Kotlin

Kotlin is a statically typed language developed by JetBrains. Its target platforms include the JVM, Android, LLVM, and JavaScript. JetBrains develops and maintains several tools specifically for the React community: React bindings as well as Create React Kotlin App. The latter helps you start building React apps with Kotlin with no build configuration.

Other Languages

Note there are other statically typed languages that compile to JavaScript and are thus React compatible. For example, F#/Fable with elmish-react. Check out their respective sites for more information, and feel free to add more statically typed languages that work with React to this page!

Strict Mode

StrictMode is a tool for highlighting potential problems in an application. Like Fragment, StrictMode does not render any visible UI. It activates additional checks and warnings for its descendants.
Note: Strict mode checks are run in development mode only; they do not impact the production build.
You can enable strict mode for any part of your application. For example: import React from 'react'; function ExampleApplication() { return ( <div> <Header /> <React.StrictMode> <div> <ComponentOne /> <ComponentTwo /> </div> </React.StrictMode> <Footer /> </div> ); } In the above example, strict mode checks will not be run against the Header and Footer components. However, ComponentOne and ComponentTwo, as well as all of their descendants, will have the checks. StrictMode currently helps with:
  • Identifying components with unsafe lifecycles
  • Warning about legacy string ref API usage
  • Warning about deprecated findDOMNode usage
  • Detecting unexpected side effects
  • Detecting legacy context API
Additional functionality will be added with future releases of React.

Identifying unsafe lifecycles

As explained in this blog post, certain legacy lifecycle methods are unsafe for use in async React applications. However, if your application uses third party libraries, it can be difficult to ensure that these lifecycles aren't being used. Fortunately, strict mode can help with this! When strict mode is enabled, React compiles a list of all class components using the unsafe lifecycles, and logs a warning message with information about these components, like so: Addressing the issues identified by strict mode now will make it easier for you to take advantage of concurrent rendering in future releases of React.

Warning about legacy string ref API usage

Previously, React provided two ways for managing refs: the legacy string ref API and the callback API. Although the string ref API was the more convenient of the two, it had several downsides and so our official recommendation was to use the callback form instead. React 16.3 added a third option that offers the convenience of a string ref without any of the downsides: class MyComponent extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef(); } render() { return <input type="text" ref={this.inputRef} />; } componentDidMount() { this.inputRef.current.focus(); } } Since object refs were largely added as a replacement for string refs, strict mode now warns about usage of string refs.
Note: Callback refs will continue to be supported in addition to the new createRef API. You don't need to replace callback refs in your components. They are slightly more flexible, so they will remain as an advanced feature.
Learn more about the new createRef API here.

Warning about deprecated findDOMNode usage

React used to support findDOMNode to search the tree for a DOM node given a class instance. Normally you don't need this because you can attach a ref directly to a DOM node. findDOMNode can also be used on class components but this was breaking abstraction levels by allowing a parent to demand that certain children was rendered. It creates a refactoring hazard where you can't change the implementation details of a component because a parent might be reaching into its DOM node. findDOMNode only returns the first child, but with the use of Fragments, it is possible for a component to render multiple DOM nodes. findDOMNode is a one time read API. It only gave you an answer when you asked for it. If a child component renders a different node, there is no way to handle this change. Therefore findDOMNode only worked if components always return a single DOM node that never changes. You can instead make this explicit by passing a ref to your custom component and pass that along to the DOM using ref forwarding. You can also add a wrapper DOM node in your component and attach a ref directly to it. class MyComponent extends React.Component { constructor(props) { super(props); this.wrapper = React.createRef(); } render() { return <div ref={this.wrapper}>{this.props.children}</div>; } }
Note: In CSS, the display: contents attribute can be used if you don't want the node to be part of the layout.

Detecting unexpected side effects

Conceptually, React does work in two phases:
  • The render phase determines what changes need to be made to e.g. the DOM. During this phase, React calls render and then compares the result to the previous render.
  • The commit phase is when React applies any changes. (In the case of React DOM, this is when React inserts, updates, and removes DOM nodes.) React also calls lifecycles like componentDidMount and componentDidUpdate during this phase.
The commit phase is usually very fast, but rendering can be slow. For this reason, the upcoming concurrent mode (which is not enabled by default yet) breaks the rendering work into pieces, pausing and resuming the work to avoid blocking the browser. This means that React may invoke render phase lifecycles more than once before committing, or it may invoke them without committing at all (because of an error or a higher priority interruption). Render phase lifecycles include the following class component methods:
  • constructor
  • componentWillMount (or UNSAFE_componentWillMount)
  • componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
  • componentWillUpdate (or UNSAFE_componentWillUpdate)
  • getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • setState updater functions (the first argument)
Because the above methods might be called more than once, it's important that they do not contain side-effects. Ignoring this rule can lead to a variety of problems, including memory leaks and invalid application state. Unfortunately, it can be difficult to detect these problems as they can often be non-deterministic. Strict mode can't automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:
  • Class component constructor, render, and shouldComponentUpdate methods
  • Class component static getDerivedStateFromProps method
  • Function component bodies
  • State updater functions (the first argument to setState)
  • Functions passed to useState, useMemo, or useReducer
Note: This only applies to development mode. Lifecycles will not be double-invoked in production mode.
For example, consider the following code: class TopLevelRoute extends React.Component { constructor(props) { super(props); SharedApplicationState.recordEvent('ExampleComponent'); } } At first glance, this code might not seem problematic. But if SharedApplicationState.recordEvent is not idempotent, then instantiating this component multiple times could lead to invalid application state. This sort of subtle bug might not manifest during development, or it might do so inconsistently and so be overlooked. By intentionally double-invoking methods like the component constructor, strict mode makes patterns like this easier to spot.
Note: Starting with React 17, React automatically modifies the console methods like console.log() to silence the logs in the second call to lifecycle functions. However, it may cause undesired behavior in certain cases where a workaround can be used.

Detecting legacy context API

The legacy context API is error-prone, and will be removed in a future major version. It still works for all 16.x releases but will show this warning message in strict mode: Read the new context API documentation to help migrate to the new version.

Typechecking With PropTypes

Note: React.PropTypes has moved into a different package since React v15.5. Please use the prop-types library instead. We provide a codemod script to automate the conversion.
As your app grows, you can catch a lot of bugs with typechecking. For some applications, you can use JavaScript extensions like Flow or TypeScript to typecheck your whole application. But even if you don't use those, React has some built-in typechecking abilities. To run typechecking on the props for a component, you can assign the special propTypes property: import PropTypes from 'prop-types'; class Greeting extends React.Component { render() { return ( <h2>Hello, {this.props.name}</h2> ); } } Greeting.propTypes = { name: PropTypes.string }; In this example, we are using a class component, but the same functionality could also be applied to function components, or components created by React.memo or React.forwardRef. PropTypes exports a range of validators that can be used to make sure the data you receive is valid. In this example, we're using PropTypes.string. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. For performance reasons, propTypes is only checked in development mode.

PropTypes

Here is an example documenting the different validators provided: import PropTypes from 'prop-types'; MyComponent.propTypes = { // You can declare that a prop is a specific JS type. By default, these // are all optional. optionalArray: PropTypes.array, optionalBool: PropTypes.bool, optionalFunc: PropTypes.func, optionalNumber: PropTypes.number, optionalObject: PropTypes.object, optionalString: PropTypes.string, optionalSymbol: PropTypes.symbol, // Anything that can be rendered: numbers, strings, elements or an array // (or fragment) containing these types. optionalNode: PropTypes.node, // A React element. optionalElement: PropTypes.element, // A React element type (ie. MyComponent). optionalElementType: PropTypes.elementType, // You can also declare that a prop is an instance of a class. This uses // JS's instanceof operator. optionalMessage: PropTypes.instanceOf(Message), // You can ensure that your prop is limited to specific values by treating // it as an enum. optionalEnum: PropTypes.oneOf(['News', 'Photos']), // An object that could be one of many types optionalUnion: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, PropTypes.instanceOf(Message) ]), // An array of a certain type optionalArrayOf: PropTypes.arrayOf(PropTypes.number), // An object with property values of a certain type optionalObjectOf: PropTypes.objectOf(PropTypes.number), // An object taking on a particular shape optionalObjectWithShape: PropTypes.shape({ color: PropTypes.string, fontSize: PropTypes.number }), // An object with warnings on extra properties optionalObjectWithStrictShape: PropTypes.exact({ name: PropTypes.string, quantity: PropTypes.number }), // You can chain any of the above with `isRequired` to make sure a warning // is shown if the prop isn't provided. requiredFunc: PropTypes.func.isRequired, // A required value of any data type requiredAny: PropTypes.any.isRequired, // You can also specify a custom validator. It should return an Error // object if the validation fails. Don't `console.warn` or throw, as this // won't work inside `oneOfType`. customProp: function(props, propName, componentName) { if (!/matchme/.test(props[propName])) { return new Error( 'Invalid prop `' + propName + '` supplied to' + ' `' + componentName + '`. Validation failed.' ); } }, // You can also supply a custom validator to `arrayOf` and `objectOf`. // It should return an Error object if the validation fails. The validator // will be called for each key in the array or object. The first two // arguments of the validator are the array or object itself, and the // current item's key. customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) { if (!/matchme/.test(propValue[key])) { return new Error( 'Invalid prop `' + propFullName + '` supplied to' + ' `' + componentName + '`. Validation failed.' ); } }) };

Requiring Single Child

With PropTypes.element you can specify that only a single child can be passed to a component as children. import PropTypes from 'prop-types'; class MyComponent extends React.Component { render() { // This must be exactly one element or it will warn. const children = this.props.children; return ( <div> {children} </div> ); } } MyComponent.propTypes = { children: PropTypes.element.isRequired };

Default Prop Values

You can define default values for your props by assigning to the special defaultProps property: class Greeting extends React.Component { render() { return ( <h2>Hello, {this.props.name}</h2> ); } } // Specifies the default values for props: Greeting.defaultProps = { name: 'Stranger' }; // Renders "Hello, Stranger": ReactDOM.render( <Greeting />, document.getElementById('example') ); If you are using a Babel transform like transform-class-properties , you can also declare defaultProps as static property within a React component class. This syntax has not yet been finalized though and will require a compilation step to work within a browser. For more information, see the class fields proposal. class Greeting extends React.Component { static defaultProps = { name: 'stranger' } render() { return ( <div>Hello, {this.props.name}</div> ) } } The defaultProps will be used to ensure that this.props.name will have a value if it was not specified by the parent component. The propTypes typechecking happens after defaultProps are resolved, so typechecking will also apply to the defaultProps.

Function Components

If you are using function components in your regular development, you may want to make some small changes to allow PropTypes to be properly applied. Let's say you have a component like this: export default function HelloWorldComponent({ name }) { return ( <div>Hello, {name}</div> ) } To add PropTypes, you may want to declare the component in a separate function before exporting, like this: function HelloWorldComponent({ name }) { return ( <div>Hello, {name}</div> ) } export default HelloWorldComponent Then, you can add PropTypes directly to the HelloWorldComponent: import PropTypes from 'prop-types' function HelloWorldComponent({ name }) { return ( <div>Hello, {name}</div> ) } HelloWorldComponent.propTypes = { name: PropTypes.string } export default HelloWorldComponent

Uncontrolled Components

In most cases, we recommend using controlled components to implement forms. In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by the DOM itself. To write an uncontrolled component, instead of writing an event handler for every state update, you can use a ref to get form values from the DOM. For example, this code accepts a single name in an uncontrolled component: class NameForm extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.input = React.createRef(); } handleSubmit(event) { alert('A name was submitted: ' + this.input.current.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" ref={this.input} /> </label> <input type="submit" value="Submit" /> </form> ); } } Try it on CodePen Since an uncontrolled component keeps the source of truth in the DOM, it is sometimes easier to integrate React and non-React code when using uncontrolled components. It can also be slightly less code if you want to be quick and dirty. Otherwise, you should usually use controlled components. If it's still not clear which type of component you should use for a particular situation, you might find this article on controlled versus uncontrolled inputs to be helpful.

Default Values

In the React rendering lifecycle, the value attribute on form elements will override the value in the DOM. With an uncontrolled component, you often want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a defaultValue attribute instead of value. Changing the value of defaultValue attribute after a component has mounted will not cause any update of the value in the DOM. render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input defaultValue="Bob" type="text" ref={this.input} /> </label> <input type="submit" value="Submit" /> </form> ); } Likewise, <input type="checkbox"> and <input type="radio"> support defaultChecked, and <select> and <textarea> supports defaultValue.

The file input Tag

In HTML, an <input type="file"> lets the user choose one or more files from their device storage to be uploaded to a server or manipulated by JavaScript via the File API. <input type="file" /> In React, an <input type="file" /> is always an uncontrolled component because its value can only be set by a user, and not programmatically. You should use the File API to interact with the files. The following example shows how to create a ref to the DOM node to access file(s) in a submit handler: class FileInput extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.fileInput = React.createRef(); } handleSubmit(event) { event.preventDefault(); alert( `Selected file - ${this.fileInput.current.files[0].name}` ); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Upload file: <input type="file" ref={this.fileInput} /> </label> <br /> <button type="submit">Submit</button> </form> ); } } ReactDOM.render( <FileInput />, document.getElementById('root') ); Try it on CodePen

Web Components

React and Web Components are built to solve different problems. Web Components provide strong encapsulation for reusable components, while React provides a declarative library that keeps the DOM in sync with your data. The two goals are complementary. As a developer, you are free to use React in your Web Components, or to use Web Components in React, or both. Most people who use React don't use Web Components, but you may want to, especially if you are using third-party UI components that are written using Web Components.

Using Web Components in React

class HelloMessage extends React.Component { render() { return <div>Hello <x-search>{this.props.name}</x-search>!</div>; } }
Note: Web Components often expose an imperative API. For instance, a video Web Component might expose play() and pause() functions. To access the imperative APIs of a Web Component, you will need to use a ref to interact with the DOM node directly. If you are using third-party Web Components, the best solution is to write a React component that behaves as a wrapper for your Web Component. Events emitted by a Web Component may not properly propagate through a React render tree. You will need to manually attach event handlers to handle these events within your React components.
One common confusion is that Web Components use ¡°class¡± instead of ¡°className¡±. function BrickFlipbox() { return ( <brick-flipbox class="demo"> <div>front</div> <div>back</div> </brick-flipbox> ); }

Using React in your Web Components

class XSearch extends HTMLElement { connectedCallback() { const mountPoint = document.createElement('span'); this.attachShadow({ mode: 'open' }).appendChild(mountPoint); const name = this.getAttribute('name'); const url = 'https://www.google.com/search?q=' + encodeURIComponent(name); ReactDOM.render(<a href={url}>{name}</a>, mountPoint); } } customElements.define('x-search', XSearch);
Note: This code will not work if you transform classes with Babel. See this issue for the discussion. Include the custom-elements-es5-adapter before you load your web components to fix this issue.

React Top-Level API

React is the entry point to the React library. If you load React from a <script> tag, these top-level APIs are available on the React global. If you use ES6 with npm, you can write import React from 'react'. If you use ES5 with npm, you can write var React = require('react').

Overview

Components

React components let you split the UI into independent, reusable pieces, and think about each piece in isolation. React components can be defined by subclassing React.Component or React.PureComponent.
  • React.Component
  • React.PureComponent
If you don't use ES6 classes, you may use the create-react-class module instead. See Using React without ES6 for more information. React components can also be defined as functions which can be wrapped:
  • React.memo

Creating React Elements

We recommend using JSX to describe what your UI should look like. Each JSX element is just syntactic sugar for calling React.createElement(). You will not typically invoke the following methods directly if you are using JSX.
  • createElement()
  • createFactory()
See Using React without JSX for more information.

Transforming Elements

React provides several APIs for manipulating elements:
  • cloneElement()
  • isValidElement()
  • React.Children

Fragments

React also provides a component for rendering multiple elements without a wrapper.
  • React.Fragment

Refs

  • React.createRef
  • React.forwardRef

Suspense

Suspense lets components ¡°wait¡± for something before rendering. Today, Suspense only supports one use case: loading components dynamically with React.lazy. In the future, it will support other use cases like data fetching.
  • React.lazy
  • React.Suspense

Hooks

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. Hooks have a dedicated docs section and a separate API reference:
  • Basic Hooks
    • useState
    • useEffect
    • useContext
  • Additional Hooks
    • useReducer
    • useCallback
    • useMemo
    • useRef
    • useImperativeHandle
    • useLayoutEffect
    • useDebugValue

Reference

React.Component

React.Component is the base class for React components when they are defined using ES6 classes: class Greeting extends React.Component { render() { return <h2>Hello, {this.props.name}</h2>; } } See the React.Component API Reference for a list of methods and properties related to the base React.Component class.

React.PureComponent

React.PureComponent is similar to React.Component. The difference between them is that React.Component doesn't implement shouldComponentUpdate(), but React.PureComponent implements it with a shallow prop and state comparison. If your React component's render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.
Note React.PureComponent's shouldComponentUpdate() only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only extend PureComponent when you expect to have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data. Furthermore, React.PureComponent's shouldComponentUpdate() skips prop updates for the whole component subtree. Make sure all the children components are also ¡°pure¡±.

React.memo

const MyComponent = React.memo(function MyComponent(props) { /* render using props */ }); React.memo is a higher order component. If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result. React.memo only checks for prop changes. If your function component wrapped in React.memo has a useState or useContext Hook in its implementation, it will still rerender when state or context change. By default it will only shallowly compare complex objects in the props object. If you want control over the comparison, you can also provide a custom comparison function as the second argument. function MyComponent(props) { /* render using props */ } function areEqual(prevProps, nextProps) { /* return true if passing nextProps to render would return the same result as passing prevProps to render, otherwise return false */ } export default React.memo(MyComponent, areEqual); This method only exists as a performance optimization. Do not rely on it to ¡°prevent¡± a render, as this can lead to bugs.
Note Unlike the shouldComponentUpdate() method on class components, the areEqual function returns true if the props are equal and false if the props are not equal. This is the inverse from shouldComponentUpdate.

createElement()

React.createElement( type, [props], [...children] ) Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span'), a React component type (a class or a function), or a React fragment type. Code written with JSX will be converted to use React.createElement(). You will not typically invoke React.createElement() directly if you are using JSX. See React Without JSX to learn more.

cloneElement()

React.cloneElement( element, [props], [...children] ) Clone and return a new React element using element as the starting point. The resulting element will have the original element's props with the new props merged in shallowly. New children will replace existing children. key and ref from the original element will be preserved. React.cloneElement() is almost equivalent to: <element.type {...element.props} {...props}>{children}</element.type> However, it also preserves refs. This means that if you get a child with a ref on it, you won't accidentally steal it from your ancestor. You will get the same ref attached to your new element. This API was introduced as a replacement of the deprecated React.addons.cloneWithProps().

createFactory()

React.createFactory(type) Return a function that produces React elements of a given type. Like React.createElement(), the type argument can be either a tag name string (such as 'div' or 'span'), a React component type (a class or a function), or a React fragment type. This helper is considered legacy, and we encourage you to either use JSX or use React.createElement() directly instead. You will not typically invoke React.createFactory() directly if you are using JSX. See React Without JSX to learn more.

isValidElement()

React.isValidElement(object) Verifies the object is a React element. Returns true or false.

React.Children

React.Children provides utilities for dealing with the this.props.children opaque data structure.
React.Children.map
React.Children.map(children, function[(thisArg)]) Invokes a function on every immediate child contained within children with this set to thisArg. If children is an array it will be traversed and the function will be called for each child in the array. If children is null or undefined, this method will return null or undefined rather than an array.
Note If children is a Fragment it will be treated as a single child and not traversed.
React.Children.forEach
React.Children.forEach(children, function[(thisArg)]) Like React.Children.map() but does not return an array.
React.Children.count
React.Children.count(children) Returns the total number of components in children, equal to the number of times that a callback passed to map or forEach would be invoked.
React.Children.only
React.Children.only(children) Verifies that children has only one child (a React element) and returns it. Otherwise this method throws an error.
Note: React.Children.only() does not accept the return value of React.Children.map() because it is an array rather than a React element.
React.Children.toArray
React.Children.toArray(children) Returns the children opaque data structure as a flat array with keys assigned to each child. Useful if you want to manipulate collections of children in your render methods, especially if you want to reorder or slice this.props.children before passing it down.
Note: React.Children.toArray() changes keys to preserve the semantics of nested arrays when flattening lists of children. That is, toArray prefixes each key in the returned array so that each element's key is scoped to the input array containing it.

React.Fragment

The React.Fragment component lets you return multiple elements in a render() method without creating an additional DOM element: render() { return ( <React.Fragment> Some text. <h3>A heading</h3> </React.Fragment> ); } You can also use it with the shorthand <></> syntax. For more information, see React v16.2.0: Improved Support for Fragments.

React.createRef

React.createRef creates a ref that can be attached to React elements via the ref attribute. class MyComponent extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef(); } render() { return <input type="text" ref={this.inputRef} />; } componentDidMount() { this.inputRef.current.focus(); } }

React.forwardRef

React.forwardRef creates a React component that forwards the ref attribute it receives to another component below in the tree. This technique is not very common but is particularly useful in two scenarios:
  • Forwarding refs to DOM components
  • Forwarding refs in higher-order-components
React.forwardRef accepts a rendering function as an argument. React will call this function with props and ref as two arguments. This function should return a React node. const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children} </button> )); // You can now get a ref directly to the DOM button: const ref = React.createRef(); <FancyButton ref={ref}>Click me!</FancyButton>; In the above example, React passes a ref given to <FancyButton ref={ref}> element as a second argument to the rendering function inside the React.forwardRef call. This rendering function passes the ref to the <button ref={ref}> element. As a result, after React attaches the ref, ref.current will point directly to the <button> DOM element instance. For more information, see forwarding refs.

React.lazy

React.lazy() lets you define a component that is loaded dynamically. This helps reduce the bundle size to delay loading components that aren't used during the initial render. You can learn how to use it from our code splitting documentation. You might also want to check out this article explaining how to use it in more detail. // This component is loaded dynamically const SomeComponent = React.lazy(() => import('./SomeComponent')); Note that rendering lazy components requires that there's a <React.Suspense> component higher in the rendering tree. This is how you specify a loading indicator.
Note Using React.lazywith dynamic import requires Promises to be available in the JS environment. This requires a polyfill on IE11 and below.

React.Suspense

React.Suspense lets you specify the loading indicator in case some components in the tree below it are not yet ready to render. Today, lazy loading components is the only use case supported by <React.Suspense>: // This component is loaded dynamically const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( // Displays <Spinner> until OtherComponent loads <React.Suspense fallback={<Spinner />}> <div> <OtherComponent /> </div> </React.Suspense> ); } It is documented in our code splitting guide. Note that lazy components can be deep inside the Suspense tree ¡ª it doesn't have to wrap every one of them. The best practice is to place <Suspense> where you want to see a loading indicator, but to use lazy() wherever you want to do code splitting. While this is not supported today, in the future we plan to let Suspense handle more scenarios such as data fetching. You can read about this in our roadmap.
Note: React.lazy() and <React.Suspense> are not yet supported by ReactDOMServer. This is a known limitation that will be resolved in the future.

ReactDOM

If you load React from a <script> tag, these top-level APIs are available on the ReactDOM global. If you use ES6 with npm, you can write import ReactDOM from 'react-dom'. If you use ES5 with npm, you can write var ReactDOM = require('react-dom').

Overview

The react-dom package provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.
  • render()
  • hydrate()
  • unmountComponentAtNode()
  • findDOMNode()
  • createPortal()

Browser Support

React supports all popular browsers, including Internet Explorer 9 and above, although some polyfills are required for older browsers such as IE 9 and IE 10.
Note We don't support older browsers that don't support ES5 methods, but you may find that your apps do work in older browsers if polyfills such as es5-shim and es5-sham are included in the page. You're on your own if you choose to take this path.

Reference

render()

ReactDOM.render(element, container[, callback]) Render a React element into the DOM in the supplied container and return a reference to the component (or returns null for stateless components). If the React element was previously rendered into container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React element. If the optional callback is provided, it will be executed after the component is rendered or updated.
Note: ReactDOM.render() controls the contents of the container node you pass in. Any existing DOM elements inside are replaced when first called. Later calls use React's DOM diffing algorithm for efficient updates. ReactDOM.render() does not modify the container node (only modifies the children of the container). It may be possible to insert a component to an existing DOM node without overwriting the existing children. ReactDOM.render() currently returns a reference to the root ReactComponent instance. However, using this return value is legacy and should be avoided because future versions of React may render components asynchronously in some cases. If you need a reference to the root ReactComponent instance, the preferred solution is to attach a callback ref to the root element. Using ReactDOM.render() to hydrate a server-rendered container is deprecated and will be removed in React 17. Use hydrate() instead.

hydrate()

ReactDOM.hydrate(element, container[, callback]) Same as render(), but is used to hydrate a container whose HTML contents were rendered by ReactDOMServer. React will attempt to attach event listeners to the existing markup. React expects that the rendered content is identical between the server and the client. It can patch up differences in text content, but you should treat mismatches as bugs and fix them. In development mode, React warns about mismatches during hydration. There are no guarantees that attribute differences will be patched up in case of mismatches. This is important for performance reasons because in most apps, mismatches are rare, and so validating all markup would be prohibitively expensive. If a single element's attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the warning by adding suppressHydrationWarning={true} to the element. It only works one level deep, and is intended to be an escape hatch. Don't overuse it. Unless it's text content, React still won't attempt to patch it up, so it may remain inconsistent until future updates. If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution. Remember to be mindful of user experience on slow connections. The JavaScript code may load significantly later than the initial HTML render, so if you render something different in the client-only pass, the transition can be jarring. However, if executed well, it may be beneficial to render a ¡°shell¡± of the application on the server, and only show some of the extra widgets on the client. To learn how to do this without getting the markup mismatch issues, refer to the explanation in the previous paragraph.

unmountComponentAtNode()

ReactDOM.unmountComponentAtNode(container) Remove a mounted React component from the DOM and clean up its event handlers and state. If no component was mounted in the container, calling this function does nothing. Returns true if a component was unmounted and false if there was no component to unmount.

findDOMNode()

Note: findDOMNode is an escape hatch used to access the underlying DOM node. In most cases, use of this escape hatch is discouraged because it pierces the component abstraction. It has been deprecated in StrictMode.
ReactDOM.findDOMNode(component) If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements. In most cases, you can attach a ref to the DOM node and avoid using findDOMNode at all. When a component renders to null or false, findDOMNode returns null. When a component renders to a string, findDOMNode returns a text DOM node containing that value. As of React 16, a component may return a fragment with multiple children, in which case findDOMNode will return the DOM node corresponding to the first non-empty child.
Note: findDOMNode only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like calling findDOMNode() in render() on a component that has yet to be created) an exception will be thrown. findDOMNode cannot be used on function components.

createPortal()

ReactDOM.createPortal(child, container) Creates a portal. Portals provide a way to render children into a DOM node that exists outside the hierarchy of the DOM component.

ReactDOMServer

The ReactDOMServer object enables you to render components to static markup. Typically, it's used on a Node server: // ES modules import ReactDOMServer from 'react-dom/server'; // CommonJS var ReactDOMServer = require('react-dom/server');

Overview

The following methods can be used in both the server and browser environments:
  • renderToString()
  • renderToStaticMarkup()
These additional methods depend on a package (stream) that is only available on the server, and won't work in the browser.
  • renderToNodeStream()
  • renderToStaticNodeStream()

Reference

renderToString()

ReactDOMServer.renderToString(element) Render a React element to its initial HTML. React will return an HTML string. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes. If you call ReactDOM.hydrate() on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.

renderToStaticMarkup()

ReactDOMServer.renderToStaticMarkup(element) Similar to renderToString, except this doesn't create extra DOM attributes that React uses internally, such as data-reactroot. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save some bytes. If you plan to use React on the client to make the markup interactive, do not use this method. Instead, use renderToString on the server and ReactDOM.hydrate() on the client.

renderToNodeStream()

ReactDOMServer.renderToNodeStream(element) Render a React element to its initial HTML. Returns a Readable stream that outputs an HTML string. The HTML output by this stream is exactly equal to what ReactDOMServer.renderToString would return. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes. If you call ReactDOM.hydrate() on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.
Note: Server-only. This API is not available in the browser. The stream returned from this method will return a byte stream encoded in utf-8. If you need a stream in another encoding, take a look at a project like iconv-lite, which provides transform streams for transcoding text.

renderToStaticNodeStream()

ReactDOMServer.renderToStaticNodeStream(element) Similar to renderToNodeStream, except this doesn't create extra DOM attributes that React uses internally, such as data-reactroot. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save some bytes. The HTML output by this stream is exactly equal to what ReactDOMServer.renderToStaticMarkup would return. If you plan to use React on the client to make the markup interactive, do not use this method. Instead, use renderToNodeStream on the server and ReactDOM.hydrate() on the client.
Note: Server-only. This API is not available in the browser. The stream returned from this method will return a byte stream encoded in utf-8. If you need a stream in another encoding, take a look at a project like iconv-lite, which provides transform streams for transcoding text.

DOM Elements

React implements a browser-independent DOM system for performance and cross-browser compatibility. We took the opportunity to clean up a few rough edges in browser DOM implementations. In React, all DOM properties and attributes (including event handlers) should be camelCased. For example, the HTML attribute tabindex corresponds to the attribute tabIndex in React. The exception is aria-* and data-* attributes, which should be lowercased. For example, you can keep aria-label as aria-label.

Differences In Attributes

There are a number of attributes that work differently between React and HTML:

checked

The checked attribute is supported by <input> components of type checkbox or radio. You can use it to set whether the component is checked. This is useful for building controlled components. defaultChecked is the uncontrolled equivalent, which sets whether the component is checked when it is first mounted.

className

To specify a CSS class, use the className attribute. This applies to all regular DOM and SVG elements like <div>, <a>, and others. If you use React with Web Components (which is uncommon), use the class attribute instead.

dangerouslySetInnerHTML

dangerouslySetInnerHTML is React's replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it's easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it's dangerous. For example: function createMarkup() { return {__html: 'First &middot; Second'}; } function MyComponent() { return <div dangerouslySetInnerHTML={createMarkup()} />; }

htmlFor

Since for is a reserved word in JavaScript, React elements use htmlFor instead.

onChange

The onChange event behaves as you would expect it to: whenever a form field is changed, this event is fired. We intentionally do not use the existing browser behavior because onChange is a misnomer for its behavior and React relies on this event to handle user input in real time.

selected

If you want to mark an <option> as selected, reference the value of that option in the value of its <select> instead. Check out ¡°The select Tag¡± for detailed instructions.

style

Note Some examples in the documentation use style for convenience, but using the style attribute as the primary means of styling elements is generally not recommended. In most cases, className should be used to reference classes defined in an external CSS stylesheet. style is most often used in React applications to add dynamically-computed styles at render time. See also FAQ: Styling and CSS.
The style attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM style JavaScript property, is more efficient, and prevents XSS security holes. For example: const divStyle = { color: 'blue', backgroundImage: 'url(' + imgUrl + ')', }; function HelloWorldComponent() { return <div style={divStyle}>Hello World!</div>; } Note that styles are not autoprefixed. To support older browsers, you need to supply corresponding style properties: const divStyle = { WebkitTransition: 'all', // note the capital 'W' here msTransition: 'all' // 'ms' is the only lowercase vendor prefix }; function ComponentWithTransition() { return <div style={divStyle}>This should work cross-browser</div>; } Style keys are camelCased in order to be consistent with accessing the properties on DOM nodes from JS (e.g. node.style.backgroundImage). Vendor prefixes other than ms should begin with a capital letter. This is why WebkitTransition has an uppercase ¡°W¡±. React will automatically append a ¡°px¡± suffix to certain numeric inline style properties. If you want to use units other than ¡°px¡±, specify the value as a string with the desired unit. For example: // Result style: '10px' <div style={{ height: 10 }}> Hello World! </div> // Result style: '10%' <div style={{ height: '10%' }}> Hello World! </div> Not all style properties are converted to pixel strings though. Certain ones remain unitless (eg zoom, order, flex). A complete list of unitless properties can be seen here.

suppressContentEditableWarning

Normally, there is a warning when an element with children is also marked as contentEditable, because it won't work. This attribute suppresses that warning. Don't use this unless you are building a library like Draft.js that manages contentEditable manually.

suppressHydrationWarning

If you use server-side React rendering, normally there is a warning when the server and the client render different content. However, in some rare cases, it is very hard or impossible to guarantee an exact match. For example, timestamps are expected to differ on the server and on the client. If you set suppressHydrationWarning to true, React will not warn you about mismatches in the attributes and the content of that element. It only works one level deep, and is intended to be used as an escape hatch. Don't overuse it. You can read more about hydration in the ReactDOM.hydrate() documentation.

value

The value attribute is supported by <input>, <select> and <textarea> components. You can use it to set the value of the component. This is useful for building controlled components. defaultValue is the uncontrolled equivalent, which sets the value of the component when it is first mounted.

All Supported HTML Attributes

As of React 16, any standard or custom DOM attributes are fully supported. React has always provided a JavaScript-centric API to the DOM. Since React components often take both custom and DOM-related props, React uses the camelCase convention just like the DOM APIs: <div tabIndex={-1} /> // Just like node.tabIndex DOM API <div className="Button" /> // Just like node.className DOM API <input readOnly={true} /> // Just like node.readOnly DOM API These props work similarly to the corresponding HTML attributes, with the exception of the special cases documented above. Some of the DOM attributes supported by React include: accept acceptCharset accessKey action allowFullScreen alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge charSet checked cite classID className colSpan cols content contentEditable contextMenu controls controlsList coords crossOrigin data dateTime default defer dir disabled download draggable encType form formAction formEncType formMethod formNoValidate formTarget frameBorder headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media mediaGroup method min minLength multiple muted name noValidate nonce open optimum pattern placeholder poster preload profile radioGroup readOnly rel required reversed role rowSpan rows sandbox scope scoped scrolling seamless selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step style summary tabIndex target title type useMap value width wmode wrap Similarly, all SVG attributes are fully supported: accentHeight accumulate additive alignmentBaseline allowReorder alphabetic amplitude arabicForm ascent attributeName attributeType autoReverse azimuth baseFrequency baseProfile baselineShift bbox begin bias by calcMode capHeight clip clipPath clipPathUnits clipRule colorInterpolation colorInterpolationFilters colorProfile colorRendering contentScriptType contentStyleType cursor cx cy d decelerate descent diffuseConstant direction display divisor dominantBaseline dur dx dy edgeMode elevation enableBackground end exponent externalResourcesRequired fill fillOpacity fillRule filter filterRes filterUnits floodColor floodOpacity focusable fontFamily fontSize fontSizeAdjust fontStretch fontStyle fontVariant fontWeight format from fx fy g1 g2 glyphName glyphOrientationHorizontal glyphOrientationVertical glyphRef gradientTransform gradientUnits hanging horizAdvX horizOriginX ideographic imageRendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength kerning keyPoints keySplines keyTimes lengthAdjust letterSpacing lightingColor limitingConeAngle local markerEnd markerHeight markerMid markerStart markerUnits markerWidth mask maskContentUnits maskUnits mathematical mode numOctaves offset opacity operator order orient orientation origin overflow overlinePosition overlineThickness paintOrder panose1 pathLength patternContentUnits patternTransform patternUnits pointerEvents points pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits r radius refX refY renderingIntent repeatCount repeatDur requiredExtensions requiredFeatures restart result rotate rx ry scale seed shapeRendering slope spacing specularConstant specularExponent speed spreadMethod startOffset stdDeviation stemh stemv stitchTiles stopColor stopOpacity strikethroughPosition strikethroughThickness string stroke strokeDasharray strokeDashoffset strokeLinecap strokeLinejoin strokeMiterlimit strokeOpacity strokeWidth surfaceScale systemLanguage tableValues targetX targetY textAnchor textDecoration textLength textRendering to transform u1 u2 underlinePosition underlineThickness unicode unicodeBidi unicodeRange unitsPerEm vAlphabetic vHanging vIdeographic vMathematical values vectorEffect version vertAdvY vertOriginX vertOriginY viewBox viewTarget visibility widths wordSpacing writingMode x x1 x2 xChannelSelector xHeight xlinkActuate xlinkArcrole xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlns xmlnsXlink xmlBase xmlLang xmlSpace y y1 y2 yChannelSelector z zoomAndPan You may also use custom attributes as long as they're fully lowercase.

SyntheticEvent

This reference guide documents the SyntheticEvent wrapper that forms part of React's Event System. See the Handling Events guide to learn more.

Overview

Your event handlers will be passed instances of SyntheticEvent, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers. If you find that you need the underlying browser event for some reason, simply use the nativeEvent attribute to get it. The synthetic events are different from, and do not map directly to, the browser's native events. For example in onMouseLeave event.nativeEvent will point to a mouseout event. The specific mapping is not part of the public API and may change at any time. Every SyntheticEvent object has the following attributes: boolean bubbles boolean cancelable DOMEventTarget currentTarget boolean defaultPrevented number eventPhase boolean isTrusted DOMEvent nativeEvent void preventDefault() boolean isDefaultPrevented() void stopPropagation() boolean isPropagationStopped() void persist() DOMEventTarget target number timeStamp string type
Note: As of v17, e.persist() doesn't do anything because the SyntheticEvent is no longer pooled.
Note: As of v0.14, returning false from an event handler will no longer stop event propagation. Instead, e.stopPropagation() or e.preventDefault() should be triggered manually, as appropriate.

Supported Events

React normalizes events so that they have consistent properties across different browsers. The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.
  • Clipboard Events
  • Composition Events
  • Keyboard Events
  • Focus Events
  • Form Events
  • Generic Events
  • Mouse Events
  • Pointer Events
  • Selection Events
  • Touch Events
  • UI Events
  • Wheel Events
  • Media Events
  • Image Events
  • Animation Events
  • Transition Events
  • Other Events

Reference

Clipboard Events

Event names: onCopy onCut onPaste Properties: DOMDataTransfer clipboardData

Composition Events

Event names: onCompositionEnd onCompositionStart onCompositionUpdate Properties: string data

Keyboard Events

Event names: onKeyDown onKeyPress onKeyUp Properties: boolean altKey number charCode boolean ctrlKey boolean getModifierState(key) string key number keyCode string locale number location boolean metaKey boolean repeat boolean shiftKey number which The key property can take any of the values documented in the DOM Level 3 Events spec.

Focus Events

Event names: onFocus onBlur These focus events work on all elements in the React DOM, not just form elements. Properties: DOMEventTarget relatedTarget
onFocus
The onFocus event is called when the element (or some element inside of it) receives focus. For example, it's called when the user clicks on a text input. function Example() { return ( <input onFocus={(e) => { console.log('Focused on input'); }} placeholder="onFocus is triggered when you click this input." /> ) }
onBlur
The onBlur event handler is called when focus has left the element (or left some element inside of it). For example, it's called when the user clicks outside of a focused text input. function Example() { return ( <input onBlur={(e) => { console.log('Triggered because this input lost focus'); }} placeholder="onBlur is triggered when you click this input and then you click outside of it." /> ) }
Detecting Focus Entering and Leaving
You can use the currentTarget and relatedTarget to differentiate if the focusing or blurring events originated from outside of the parent element. Here is a demo you can copy and paste that shows how to detect focusing a child, focusing the element itself, and focus entering or leaving the whole subtree. function Example() { return ( <div tabIndex={1} onFocus={(e) => { if (e.currentTarget === e.target) { console.log('focused self'); } else { console.log('focused child', e.target); } if (!e.currentTarget.contains(e.relatedTarget)) { // Not triggered when swapping focus between children console.log('focus entered self'); } }} onBlur={(e) => { if (e.currentTarget === e.target) { console.log('unfocused self'); } else { console.log('unfocused child', e.target); } if (!e.currentTarget.contains(e.relatedTarget)) { // Not triggered when swapping focus between children console.log('focus left self'); } }} > <input id="1" /> <input id="2" /> </div> ); }

Form Events

Event names: onChange onInput onInvalid onReset onSubmit For more information about the onChange event, see Forms.

Generic Events

Event names: onError onLoad

Mouse Events

Event names: onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp The onMouseEnter and onMouseLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase. Properties: boolean altKey number button number buttons number clientX number clientY boolean ctrlKey boolean getModifierState(key) boolean metaKey number pageX number pageY DOMEventTarget relatedTarget number screenX number screenY boolean shiftKey

Pointer Events

Event names: onPointerDown onPointerMove onPointerUp onPointerCancel onGotPointerCapture onLostPointerCapture onPointerEnter onPointerLeave onPointerOver onPointerOut The onPointerEnter and onPointerLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase. Properties: As defined in the W3 spec, pointer events extend Mouse Events with the following properties: number pointerId number width number height number pressure number tangentialPressure number tiltX number tiltY number twist string pointerType boolean isPrimary A note on cross-browser support: Pointer events are not yet supported in every browser (at the time of writing this article, supported browsers include: Chrome, Firefox, Edge, and Internet Explorer). React deliberately does not polyfill support for other browsers because a standard-conform polyfill would significantly increase the bundle size of react-dom. If your application requires pointer events, we recommend adding a third party pointer event polyfill.

Selection Events

Event names: onSelect

Touch Events

Event names: onTouchCancel onTouchEnd onTouchMove onTouchStart Properties: boolean altKey DOMTouchList changedTouches boolean ctrlKey boolean getModifierState(key) boolean metaKey boolean shiftKey DOMTouchList targetTouches DOMTouchList touches

UI Events

Event names: onScroll
Note Starting with React 17, the onScroll event does not bubble in React. This matches the browser behavior and prevents the confusion when a nested scrollable element fires events on a distant parent.
Properties: number detail DOMAbstractView view

Wheel Events

Event names: onWheel Properties: number deltaMode number deltaX number deltaY number deltaZ

Media Events

Event names: onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting

Image Events

Event names: onLoad onError

Animation Events

Event names: onAnimationStart onAnimationEnd onAnimationIteration Properties: string animationName string pseudoElement float elapsedTime

Transition Events

Event names: onTransitionEnd Properties: string propertyName string pseudoElement float elapsedTime

Other Events

Event names: onToggle

Test Utilities

Importing import ReactTestUtils from 'react-dom/test-utils'; // ES6 var ReactTestUtils = require('react-dom/test-utils'); // ES5 with npm

Overview

ReactTestUtils makes it easy to test React components in the testing framework of your choice. At Facebook we use Jest for painless JavaScript testing. Learn how to get started with Jest through the Jest website's React Tutorial.
Note: We recommend using React Testing Library which is designed to enable and encourage writing tests that use your components as the end users do. Alternatively, Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components' output.
  • act()
  • mockComponent()
  • isElement()
  • isElementOfType()
  • isDOMComponent()
  • isCompositeComponent()
  • isCompositeComponentWithType()
  • findAllInRenderedTree()
  • scryRenderedDOMComponentsWithClass()
  • findRenderedDOMComponentWithClass()
  • scryRenderedDOMComponentsWithTag()
  • findRenderedDOMComponentWithTag()
  • scryRenderedComponentsWithType()
  • findRenderedComponentWithType()
  • renderIntoDocument()
  • Simulate

Reference

act()

To prepare a component for assertions, wrap the code rendering it and performing updates inside an act() call. This makes your test run closer to how React works in the browser.
Note If you use react-test-renderer, it also provides an act export that behaves the same way.
For example, let's say we have this Counter component: class Counter extends React.Component { constructor(props) { super(props); this.state = {count: 0}; this.handleClick = this.handleClick.bind(this); } componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } handleClick() { this.setState(state => ({ count: state.count + 1, })); } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={this.handleClick}> Click me </button> </div> ); } } Here is how we can test it: import React from 'react'; import ReactDOM from 'react-dom'; import { act } from 'react-dom/test-utils';import Counter from './Counter'; let container; beforeEach(() => { container = document.createElement('div'); document.body.appendChild(container); }); afterEach(() => { document.body.removeChild(container); container = null; }); it('can render and update a counter', () => { // Test first render and componentDidMount act(() => { ReactDOM.render(<Counter />, container); }); const button = container.querySelector('button'); const label = container.querySelector('p'); expect(label.textContent).toBe('You clicked 0 times'); expect(document.title).toBe('You clicked 0 times'); // Test second render and componentDidUpdate act(() => { button.dispatchEvent(new MouseEvent('click', {bubbles: true})); }); expect(label.textContent).toBe('You clicked 1 times'); expect(document.title).toBe('You clicked 1 times'); });
  • Don't forget that dispatching DOM events only works when the DOM container is added to the document. You can use a library like React Testing Library to reduce the boilerplate code.
  • The recipes document contains more details on how act() behaves, with examples and usage.

mockComponent()

mockComponent( componentClass, [mockTagName] ) Pass a mocked component module to this method to augment it with useful methods that allow it to be used as a dummy React component. Instead of rendering as usual, the component will become a simple <div> (or other tag if mockTagName is provided) containing any provided children.
Note: mockComponent() is a legacy API. We recommend using jest.mock() instead.

isElement()

isElement(element) Returns true if element is any React element.

isElementOfType()

isElementOfType( element, componentClass ) Returns true if element is a React element whose type is of a React componentClass.

isDOMComponent()

isDOMComponent(instance) Returns true if instance is a DOM component (such as a <div> or <span>).

isCompositeComponent()

isCompositeComponent(instance) Returns true if instance is a user-defined component, such as a class or a function.

isCompositeComponentWithType()

isCompositeComponentWithType( instance, componentClass ) Returns true if instance is a component whose type is of a React componentClass.

findAllInRenderedTree()

findAllInRenderedTree( tree, test ) Traverse all components in tree and accumulate all components where test(component) is true. This is not that useful on its own, but it's used as a primitive for other test utils.

scryRenderedDOMComponentsWithClass()

scryRenderedDOMComponentsWithClass( tree, className ) Finds all DOM elements of components in the rendered tree that are DOM components with the class name matching className.

findRenderedDOMComponentWithClass()

findRenderedDOMComponentWithClass( tree, className ) Like scryRenderedDOMComponentsWithClass() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.

scryRenderedDOMComponentsWithTag()

scryRenderedDOMComponentsWithTag( tree, tagName ) Finds all DOM elements of components in the rendered tree that are DOM components with the tag name matching tagName.

findRenderedDOMComponentWithTag()

findRenderedDOMComponentWithTag( tree, tagName ) Like scryRenderedDOMComponentsWithTag() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.

scryRenderedComponentsWithType()

scryRenderedComponentsWithType( tree, componentClass ) Finds all instances of components with type equal to componentClass.

findRenderedComponentWithType()

findRenderedComponentWithType( tree, componentClass ) Same as scryRenderedComponentsWithType() but expects there to be one result and returns that one result, or throws exception if there is any other number of matches besides one.

renderIntoDocument()

renderIntoDocument(element) Render a React element into a detached DOM node in the document. This function requires a DOM. It is effectively equivalent to: const domContainer = document.createElement('div'); ReactDOM.render(element, domContainer);
Note: You will need to have window, window.document and window.document.createElement globally available before you import React. Otherwise React will think it can't access the DOM and methods like setState won't work.

Other Utilities

Simulate

Simulate.{eventName}( element, [eventData] ) Simulate an event dispatch on a DOM node with optional eventData event data. Simulate has a method for every event that React understands. Clicking an element // <button ref={(node) => this.button = node}>...</button> const node = this.button; ReactTestUtils.Simulate.click(node); Changing the value of an input field and then pressing ENTER. // <input ref={(node) => this.textInput = node} /> const node = this.textInput; node.value = 'giraffe'; ReactTestUtils.Simulate.change(node); ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
Note You will have to provide any event property that you're using in your component (e.g. keyCode, which, etc¡­) as React is not creating any of these for you.

Test Renderer

Importing import TestRenderer from 'react-test-renderer'; // ES6 const TestRenderer = require('react-test-renderer'); // ES5 with npm

Overview

This package provides a React renderer that can be used to render React components to pure JavaScript objects, without depending on the DOM or a native mobile environment. Essentially, this package makes it easy to grab a snapshot of the platform view hierarchy (similar to a DOM tree) rendered by a React DOM or React Native component without using a browser or jsdom. Example: import TestRenderer from 'react-test-renderer'; function Link(props) { return <a href={props.page}>{props.children}</a>; } const testRenderer = TestRenderer.create( <Link page="https://www.facebook.com/">Facebook</Link> ); console.log(testRenderer.toJSON()); // { type: 'a', // props: { href: 'https://www.facebook.com/' }, // children: [ 'Facebook' ] } You can use Jest's snapshot testing feature to automatically save a copy of the JSON tree to a file and check in your tests that it hasn't changed: Learn more about it. You can also traverse the output to find specific nodes and make assertions about them. import TestRenderer from 'react-test-renderer'; function MyComponent() { return ( <div> <SubComponent foo="bar" /> <p className="my">Hello</p> </div> ) } function SubComponent() { return ( <p className="sub">Sub</p> ); } const testRenderer = TestRenderer.create(<MyComponent />); const testInstance = testRenderer.root; expect(testInstance.findByType(SubComponent).props.foo).toBe('bar'); expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sub']);

TestRenderer

  • TestRenderer.create()
  • TestRenderer.act()

TestRenderer instance

  • testRenderer.toJSON()
  • testRenderer.toTree()
  • testRenderer.update()
  • testRenderer.unmount()
  • testRenderer.getInstance()
  • testRenderer.root

TestInstance

  • testInstance.find()
  • testInstance.findByType()
  • testInstance.findByProps()
  • testInstance.findAll()
  • testInstance.findAllByType()
  • testInstance.findAllByProps()
  • testInstance.instance
  • testInstance.type
  • testInstance.props
  • testInstance.parent
  • testInstance.children

Reference

TestRenderer.create()

TestRenderer.create(element, options); Create a TestRenderer instance with the passed React element. It doesn't use the real DOM, but it still fully renders the component tree into memory so you can make assertions about it. Returns a TestRenderer instance.

TestRenderer.act()

TestRenderer.act(callback); Similar to the act() helper from react-dom/test-utils, TestRenderer.act prepares a component for assertions. Use this version of act() to wrap calls to TestRenderer.create and testRenderer.update. import {create, act} from 'react-test-renderer'; import App from './app.js'; // The component being tested // render the component let root; act(() => { root = create(<App value={1}/>) }); // make assertions on root expect(root.toJSON()).toMatchSnapshot(); // update with some different props act(() => { root.update(<App value={2}/>); }) // make assertions on root expect(root.toJSON()).toMatchSnapshot();

testRenderer.toJSON()

testRenderer.toJSON() Return an object representing the rendered tree. This tree only contains the platform-specific nodes like <div> or <View> and their props, but doesn't contain any user-written components. This is handy for snapshot testing.

testRenderer.toTree()

testRenderer.toTree() Return an object representing the rendered tree. The representation is more detailed than the one provided by toJSON(), and includes the user-written components. You probably don't need this method unless you're writing your own assertion library on top of the test renderer.

testRenderer.update()

testRenderer.update(element) Re-render the in-memory tree with a new root element. This simulates a React update at the root. If the new element has the same type and key as the previous element, the tree will be updated; otherwise, it will re-mount a new tree.

testRenderer.unmount()

testRenderer.unmount() Unmount the in-memory tree, triggering the appropriate lifecycle events.

testRenderer.getInstance()

testRenderer.getInstance() Return the instance corresponding to the root element, if available. This will not work if the root element is a function component because they don't have instances.

testRenderer.root

testRenderer.root Returns the root ¡°test instance¡± object that is useful for making assertions about specific nodes in the tree. You can use it to find other ¡°test instances¡± deeper below.

testInstance.find()

testInstance.find(test) Find a single descendant test instance for which test(testInstance) returns true. If test(testInstance) does not return true for exactly one test instance, it will throw an error.

testInstance.findByType()

testInstance.findByType(type) Find a single descendant test instance with the provided type. If there is not exactly one test instance with the provided type, it will throw an error.

testInstance.findByProps()

testInstance.findByProps(props) Find a single descendant test instance with the provided props. If there is not exactly one test instance with the provided props, it will throw an error.

testInstance.findAll()

testInstance.findAll(test) Find all descendant test instances for which test(testInstance) returns true.

testInstance.findAllByType()

testInstance.findAllByType(type) Find all descendant test instances with the provided type.

testInstance.findAllByProps()

testInstance.findAllByProps(props) Find all descendant test instances with the provided props.

testInstance.instance

testInstance.instance The component instance corresponding to this test instance. It is only available for class components, as function components don't have instances. It matches the this value inside the given component.

testInstance.type

testInstance.type The component type corresponding to this test instance. For example, a <Button /> component has a type of Button.

testInstance.props

testInstance.props The props corresponding to this test instance. For example, a <Button size="small" /> component has {size: 'small'} as props.

testInstance.parent

testInstance.parent The parent test instance of this test instance.

testInstance.children

testInstance.children The children test instances of this test instance.

Ideas

You can pass createNodeMock function to TestRenderer.create as the option, which allows for custom mock refs. createNodeMock accepts the current element and should return a mock ref object. This is useful when you test a component that relies on refs. import TestRenderer from 'react-test-renderer'; class MyComponent extends React.Component { constructor(props) { super(props); this.input = null; } componentDidMount() { this.input.focus(); } render() { return <input type="text" ref={el => this.input = el} /> } } let focused = false; TestRenderer.create( <MyComponent />, { createNodeMock: (element) => { if (element.type === 'input') { // mock a focus function return { focus: () => { focused = true; } }; } return null; } } ); expect(focused).toBe(true);

JavaScript Environment Requirements

React 16 depends on the collection types Map and Set. If you support older browsers and devices which may not yet provide these natively (e.g. IE < 11) or which have non-compliant implementations (e.g. IE 11), consider including a global polyfill in your bundled application, such as core-js. A polyfilled environment for React 16 using core-js to support older browsers might look like: import 'core-js/es/map'; import 'core-js/es/set'; import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <h2>Hello, world!</h2>, document.getElementById('root') ); React also depends on requestAnimationFrame (even in test environments).
You can use the raf package to shim requestAnimationFrame: import 'raf/polyfill';

Glossary of React Terms

Single-page Application

A single-page application is an application that loads a single HTML page and all the necessary assets (such as JavaScript and CSS) required for the application to run. Any interactions with the page or subsequent pages do not require a round trip to the server which means the page is not reloaded. Though you may build a single-page application in React, it is not a requirement. React can also be used for enhancing small parts of existing websites with additional interactivity. Code written in React can coexist peacefully with markup rendered on the server by something like PHP, or with other client-side libraries. In fact, this is exactly how React is being used at Facebook.

ES6, ES2015, ES2016, etc

These acronyms all refer to the most recent versions of the ECMAScript Language Specification standard, which the JavaScript language is an implementation of. The ES6 version (also known as ES2015) includes many additions to the previous versions such as: arrow functions, classes, template literals, let and const statements. You can learn more about specific versions here.

Compilers

A JavaScript compiler takes JavaScript code, transforms it and returns JavaScript code in a different format. The most common use case is to take ES6 syntax and transform it into syntax that older browsers are capable of interpreting. Babel is the compiler most commonly used with React.

Bundlers

Bundlers take JavaScript and CSS code written as separate modules (often hundreds of them), and combine them together into a few files better optimized for the browsers. Some bundlers commonly used in React applications include Webpack and Browserify.

Package Managers

Package managers are tools that allow you to manage dependencies in your project. npm and Yarn are two package managers commonly used in React applications. Both of them are clients for the same npm package registry.

CDN

CDN stands for Content Delivery Network. CDNs deliver cached, static content from a network of servers across the globe.

JSX

JSX is a syntax extension to JavaScript. It is similar to a template language, but it has full power of JavaScript. JSX gets compiled to React.createElement() calls which return plain JavaScript objects called ¡°React elements¡±. To get a basic introduction to JSX see the docs here and find a more in-depth tutorial on JSX here. React DOM uses camelCase property naming convention instead of HTML attribute names. For example, tabindex becomes tabIndex in JSX. The attribute class is also written as className since class is a reserved word in JavaScript: const name = 'Clementine'; ReactDOM.render( <h2 className="hello">My name is {name}!</h2>, document.getElementById('root') );

Elements

React elements are the building blocks of React applications. One might confuse elements with a more widely known concept of ¡°components¡±. An element describes what you want to see on the screen. React elements are immutable. const element = <h2>Hello, world</h2>; Typically, elements are not used directly, but get returned from components.

Components

React components are small, reusable pieces of code that return a React element to be rendered to the page. The simplest version of React component is a plain JavaScript function that returns a React element: function Welcome(props) { return <h2>Hello, {props.name}</h2>; } Components can also be ES6 classes: class Welcome extends React.Component { render() { return <h2>Hello, {this.props.name}</h2>; } } Components can be broken down into distinct pieces of functionality and used within other components. Components can return other components, arrays, strings and numbers. A good rule of thumb is that if a part of your UI is used several times (Button, Panel, Avatar), or is complex enough on its own (App, FeedStory, Comment), it is a good candidate to be a reusable component. Component names should also always start with a capital letter (<Wrapper/> not <wrapper/>). See this documentation for more information on rendering components.

props

props are inputs to a React component. They are data passed down from a parent component to a child component. Remember that props are readonly. They should not be modified in any way: // Wrong! props.number = 42; If you need to modify some value in response to user input or a network response, use state instead.

props.children

props.children is available on every component. It contains the content between the opening and closing tags of a component. For example: <Welcome>Hello world!</Welcome> The string Hello world! is available in props.children in the Welcome component: function Welcome(props) { return <p>{props.children}</p>; } For components defined as classes, use this.props.children: class Welcome extends React.Component { render() { return <p>{this.props.children}</p>; } }

state

A component needs state when some data associated with it changes over time. For example, a Checkbox component might need isChecked in its state, and a NewsFeed component might want to keep track of fetchedPosts in its state. The most important difference between state and props is that props are passed from a parent component, but state is managed by the component itself. A component cannot change its props, but it can change its state. For each particular piece of changing data, there should be just one component that ¡°owns¡± it in its state. Don't try to synchronize states of two different components. Instead, lift it up to their closest shared ancestor, and pass it down as props to both of them.

Lifecycle Methods

Lifecycle methods are custom functionality that gets executed during the different phases of a component. There are methods available when the component gets created and inserted into the DOM (mounting), when the component updates, and when the component gets unmounted or removed from the DOM.

Controlled vs. Uncontrolled Components

React has two different approaches to dealing with form inputs. An input form element whose value is controlled by React is called a controlled component. When a user enters data into a controlled component a change event handler is triggered and your code decides whether the input is valid (by re-rendering with the updated value). If you do not re-render then the form element will remain unchanged. An uncontrolled component works like form elements do outside of React. When a user inputs data into a form field (an input box, dropdown, etc) the updated information is reflected without React needing to do anything. However, this also means that you can't force the field to have a certain value. In most cases you should use controlled components.

Keys

A ¡°key¡± is a special string attribute you need to include when creating arrays of elements. Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside an array to give the elements a stable identity. Keys only need to be unique among sibling elements in the same array. They don't need to be unique across the whole application or even a single component. Don't pass something like Math.random() to keys. It is important that keys have a ¡°stable identity¡± across re-renders so that React can determine when items are added, removed, or re-ordered. Ideally, keys should correspond to unique and stable identifiers coming from your data, such as post.id.

Refs

React supports a special attribute that you can attach to any component. The ref attribute can be an object created by React.createRef() function or a callback function, or a string (in legacy API). When the ref attribute is a callback function, the function receives the underlying DOM element or class instance (depending on the type of element) as its argument. This allows you to have direct access to the DOM element or component instance. Use refs sparingly. If you find yourself often using refs to ¡°make things happen¡± in your app, consider getting more familiar with top-down data flow.

Events

Handling events with React elements has some syntactic differences:
  • React event handlers are named using camelCase, rather than lowercase.
  • With JSX you pass a function as the event handler, rather than a string.

Reconciliation

When a component's props or state change, React decides whether an actual DOM update is necessary by comparing the newly returned element with the previously rendered one. When they are not equal, React will update the DOM. This process is called ¡°reconciliation¡±.

Introducing Hooks

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } This new function useState is the first ¡°Hook¡± we'll learn about, but this example is just a teaser. Don't worry if it doesn't make sense yet! You can start learning Hooks on the next page. On this page, we'll continue by explaining why we're adding Hooks to React and how they can help you write great applications.
Note React 16.8.0 is the first release to support Hooks. When upgrading, don't forget to update all packages, including React DOM. React Native supports Hooks since the 0.59 release of React Native.

Video Introduction

At React Conf 2018, Sophie Alpert and Dan Abramov introduced Hooks, followed by Ryan Florence demonstrating how to refactor an application to use them. Watch the video here:

No Breaking Changes

Before we continue, note that Hooks are:
  • Completely opt-in. You can try Hooks in a few components without rewriting any existing code. But you don't have to learn or use Hooks right now if you don't want to.
  • 100% backwards-compatible. Hooks don't contain any breaking changes.
  • Available now. Hooks are now available with the release of v16.8.0.
There are no plans to remove classes from React. You can read more about the gradual adoption strategy for Hooks in the bottom section of this page. Hooks don't replace your knowledge of React concepts. Instead, Hooks provide a more direct API to the React concepts you already know: props, state, context, refs, and lifecycle. As we will show later, Hooks also offer a new powerful way to combine them. If you just want to start learning Hooks, feel free to jump directly to the next page! You can also keep reading this page to learn more about why we're adding Hooks, and how we're going to start using them without rewriting our applications.

Motivation

Hooks solve a wide variety of seemingly unconnected problems in React that we've encountered over five years of writing and maintaining tens of thousands of components. Whether you're learning React, use it daily, or even prefer a different library with a similar component model, you might recognize some of these problems.

It's hard to reuse stateful logic between components

React doesn't offer a way to ¡°attach¡± reusable behavior to a component (for example, connecting it to a store). If you've worked with React for a while, you may be familiar with patterns like render props and higher-order components that try to solve this. But these patterns require you to restructure your components when you use them, which can be cumbersome and make code harder to follow. If you look at a typical React application in React DevTools, you will likely find a ¡°wrapper hell¡± of components surrounded by layers of providers, consumers, higher-order components, render props, and other abstractions. While we could filter them out in DevTools, this points to a deeper underlying problem: React needs a better primitive for sharing stateful logic. With Hooks, you can extract stateful logic from a component so it can be tested independently and reused. Hooks allow you to reuse stateful logic without changing your component hierarchy. This makes it easy to share Hooks among many components or with the community. We'll discuss this more in Building Your Own Hooks.

Complex components become hard to understand

We've often had to maintain components that started out simple but grew into an unmanageable mess of stateful logic and side effects. Each lifecycle method often contains a mix of unrelated logic. For example, components might perform some data fetching in componentDidMount and componentDidUpdate. However, the same componentDidMount method might also contain some unrelated logic that sets up event listeners, with cleanup performed in componentWillUnmount. Mutually related code that changes together gets split apart, but completely unrelated code ends up combined in a single method. This makes it too easy to introduce bugs and inconsistencies. In many cases it's not possible to break these components into smaller ones because the stateful logic is all over the place. It's also difficult to test them. This is one of the reasons many people prefer to combine React with a separate state management library. However, that often introduces too much abstraction, requires you to jump between different files, and makes reusing components more difficult. To solve this, Hooks let you split one component into smaller functions based on what pieces are related (such as setting up a subscription or fetching data), rather than forcing a split based on lifecycle methods. You may also opt into managing the component's local state with a reducer to make it more predictable. We'll discuss this more in Using the Effect Hook.

Classes confuse both people and machines

In addition to making code reuse and code organization more difficult, we've found that classes can be a large barrier to learning React. You have to understand how this works in JavaScript, which is very different from how it works in most languages. You have to remember to bind the event handlers. Without unstable syntax proposals, the code is very verbose. People can understand props, state, and top-down data flow perfectly well but still struggle with classes. The distinction between function and class components in React and when to use each one leads to disagreements even between experienced React developers. Additionally, React has been out for about five years, and we want to make sure it stays relevant in the next five years. As Svelte, Angular, Glimmer, and others show, ahead-of-time compilation of components has a lot of future potential. Especially if it's not limited to templates. Recently, we've been experimenting with component folding using Prepack, and we've seen promising early results. However, we found that class components can encourage unintentional patterns that make these optimizations fall back to a slower path. Classes present issues for today's tools, too. For example, classes don't minify very well, and they make hot reloading flaky and unreliable. We want to present an API that makes it more likely for code to stay on the optimizable path. To solve these problems, Hooks let you use more of React's features without classes. Conceptually, React components have always been closer to functions. Hooks embrace functions, but without sacrificing the practical spirit of React. Hooks provide access to imperative escape hatches and don't require you to learn complex functional or reactive programming techniques.
Examples Hooks at a Glance is a good place to start learning Hooks.

Gradual Adoption Strategy

TLDR: There are no plans to remove classes from React.
We know that React developers are focused on shipping products and don't have time to look into every new API that's being released. Hooks are very new, and it might be better to wait for more examples and tutorials before considering learning or adopting them. We also understand that the bar for adding a new primitive to React is extremely high. For curious readers, we have prepared a detailed RFC that dives into motivation with more details, and provides extra perspective on the specific design decisions and related prior art. Crucially, Hooks work side-by-side with existing code so you can adopt them gradually. There is no rush to migrate to Hooks. We recommend avoiding any ¡°big rewrites¡±, especially for existing, complex class components. It takes a bit of a mindshift to start ¡°thinking in Hooks¡±. In our experience, it's best to practice using Hooks in new and non-critical components first, and ensure that everybody on your team feels comfortable with them. After you give Hooks a try, please feel free to send us feedback, positive or negative. We intend for Hooks to cover all existing use cases for classes, but we will keep supporting class components for the foreseeable future. At Facebook, we have tens of thousands of components written as classes, and we have absolutely no plans to rewrite them. Instead, we are starting to use Hooks in the new code side by side with classes.

Frequently Asked Questions

We've prepared a Hooks FAQ page that answers the most common questions about Hooks.

Next Steps

By the end of this page, you should have a rough idea of what problems Hooks are solving, but many details are probably unclear. Don't worry! Let's now go to the next page where we start learning about Hooks by example.

Hooks at a Glance

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. Hooks are backwards-compatible. This page provides an overview of Hooks for experienced React users. This is a fast-paced overview. If you get confused, look for a yellow box like this:
Detailed Explanation Read the Motivation to learn why we're introducing Hooks to React.
¡ü¡ü¡ü Each section ends with a yellow box like this. They link to detailed explanations.

State Hook

This example renders a counter. When you click the button, it increments the value: import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } Here, useState is a Hook (we'll talk about what this means in a moment). We call it inside a function component to add some local state to it. React will preserve this state between re-renders. useState returns a pair: the current state value and a function that lets you update it. You can call this function from an event handler or somewhere else. It's similar to this.setState in a class, except it doesn't merge the old and new state together. (We'll show an example comparing useState to this.state in Using the State Hook.) The only argument to useState is the initial state. In the example above, it is 0 because our counter starts from zero. Note that unlike this.state, the state here doesn't have to be an object ¡ª although it can be if you want. The initial state argument is only used during the first render.
Declaring multiple state variables
You can use the State Hook more than once in a single component: function ExampleWithManyStates() { // Declare multiple state variables! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); // ... } The array destructuring syntax lets us give different names to the state variables we declared by calling useState. These names aren't a part of the useState API. Instead, React assumes that if you call useState many times, you do it in the same order during every render. We'll come back to why this works and when this is useful later.
But what is a Hook?
Hooks are functions that let you ¡°hook into¡± React state and lifecycle features from function components. Hooks don't work inside classes ¡ª they let you use React without classes. (We don't recommend rewriting your existing components overnight but you can start using Hooks in the new ones if you'd like.) React provides a few built-in Hooks like useState. You can also create your own Hooks to reuse stateful behavior between different components. We'll look at the built-in Hooks first.
Detailed Explanation You can learn more about the State Hook on a dedicated page: Using the State Hook.

Effect Hook

You've likely performed data fetching, subscriptions, or manually changing the DOM from React components before. We call these operations ¡°side effects¡± (or ¡°effects¡± for short) because they can affect other components and can't be done during rendering. The Effect Hook, useEffect, adds the ability to perform side effects from a function component. It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in React classes, but unified into a single API. (We'll show examples comparing useEffect to these methods in Using the Effect Hook.) For example, this component sets the document title after React updates the DOM: import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } When you call useEffect, you're telling React to run your ¡°effect¡± function after flushing changes to the DOM. Effects are declared inside the component so they have access to its props and state. By default, React runs the effects after every render ¡ª including the first render. (We'll talk more about how this compares to class lifecycles in Using the Effect Hook.) Effects may also optionally specify how to ¡°clean up¡± after them by returning a function. For example, this component uses an effect to subscribe to a friend's online status, and cleans up by unsubscribing from it: import React, { useState, useEffect } from 'react'; function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; } In this example, React would unsubscribe from our ChatAPI when the component unmounts, as well as before re-running the effect due to a subsequent render. (If you want, there's a way to tell React to skip re-subscribing if the props.friend.id we passed to ChatAPI didn't change.) Just like with useState, you can use more than a single effect in a component: function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); function handleStatusChange(status) { setIsOnline(status.isOnline); } // ... Hooks let you organize side effects in a component by what pieces are related (such as adding and removing a subscription), rather than forcing a split based on lifecycle methods.
Detailed Explanation You can learn more about useEffect on a dedicated page: Using the Effect Hook.

Rules of Hooks

Hooks are JavaScript functions, but they impose two additional rules:
  • Only call Hooks at the top level. Don't call Hooks inside loops, conditions, or nested functions.
  • Only call Hooks from React function components. Don't call Hooks from regular JavaScript functions. (There is just one other valid place to call Hooks ¡ª your own custom Hooks. We'll learn about them in a moment.)
We provide a linter plugin to enforce these rules automatically. We understand these rules might seem limiting or confusing at first, but they are essential to making Hooks work well.
Detailed Explanation You can learn more about these rules on a dedicated page: Rules of Hooks.

Building Your Own Hooks

Sometimes, we want to reuse some stateful logic between components. Traditionally, there were two popular solutions to this problem: higher-order components and render props. Custom Hooks let you do this, but without adding more components to your tree. Earlier on this page, we introduced a FriendStatus component that calls the useState and useEffect Hooks to subscribe to a friend's online status. Let's say we also want to reuse this subscription logic in another component. First, we'll extract this logic into a custom Hook called useFriendStatus: import React, { useState, useEffect } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; } It takes friendID as an argument, and returns whether our friend is online. Now we can use it from both components: function FriendStatus(props) { const isOnline = useFriendStatus(props.friend.id); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; } function FriendListItem(props) { const isOnline = useFriendStatus(props.friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li> ); } The state of each component is completely independent. Hooks are a way to reuse stateful logic, not state itself. In fact, each call to a Hook has a completely isolated state ¡ª so you can even use the same custom Hook twice in one component. Custom Hooks are more of a convention than a feature. If a function's name starts with ¡±use¡± and it calls other Hooks, we say it is a custom Hook. The useSomething naming convention is how our linter plugin is able to find bugs in the code using Hooks. You can write custom Hooks that cover a wide range of use cases like form handling, animation, declarative subscriptions, timers, and probably many more we haven't considered. We are excited to see what custom Hooks the React community will come up with.
Detailed Explanation You can learn more about custom Hooks on a dedicated page: Building Your Own Hooks.

Other Hooks

There are a few less commonly used built-in Hooks that you might find useful. For example, useContext lets you subscribe to React context without introducing nesting: function Example() { const locale = useContext(LocaleContext); const theme = useContext(ThemeContext); // ... } And useReducer lets you manage local state of complex components with a reducer: function Todos() { const [todos, dispatch] = useReducer(todosReducer); // ...
Detailed Explanation You can learn more about all the built-in Hooks on a dedicated page: Hooks API Reference.

Next Steps

Phew, that was fast! If some things didn't quite make sense or you'd like to learn more in detail, you can read the next pages, starting with the State Hook documentation. You can also check out the Hooks API reference and the Hooks FAQ. Finally, don't miss the introduction page which explains why we're adding Hooks and how we'll start using them side by side with classes ¡ª without rewriting our apps.

Using the State Hook

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. The introduction page used this example to get familiar with Hooks: import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } We'll start learning about Hooks by comparing this code to an equivalent class example.

Equivalent Class Example

If you used classes in React before, this code should look familiar: class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } } The state starts as { count: 0 }, and we increment state.count when the user clicks a button by calling this.setState(). We'll use snippets from this class throughout the page.
Note You might be wondering why we're using a counter here instead of a more realistic example. This is to help us focus on the API while we're still making our first steps with Hooks.

Hooks and Function Components

As a reminder, function components in React look like this: const Example = (props) => { // You can use Hooks here! return <div />; } or this: function Example(props) { // You can use Hooks here! return <div />; } You might have previously known these as ¡°stateless components¡±. We're now introducing the ability to use React state from these, so we prefer the name ¡°function components¡±. Hooks don't work inside classes. But you can use them instead of writing classes.

What's a Hook?

Our new example starts by importing the useState Hook from React: import React, { useState } from 'react'; function Example() { // ... } What is a Hook? A Hook is a special function that lets you ¡°hook into¡± React features. For example, useState is a Hook that lets you add React state to function components. We'll learn other Hooks later. When would I use a Hook? If you write a function component and realize you need to add some state to it, previously you had to convert it to a class. Now you can use a Hook inside the existing function component. We're going to do that right now!
Note: There are some special rules about where you can and can't use Hooks within a component. We'll learn them in Rules of Hooks.

Declaring a State Variable

In a class, we initialize the count state to 0 by setting this.state to { count: 0 } in the constructor: class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } In a function component, we have no this, so we can't assign or read this.state. Instead, we call the useState Hook directly inside our component: import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); What does calling useState do? It declares a ¡°state variable¡±. Our variable is called count but we could call it anything else, like banana. This is a way to ¡°preserve¡± some values between the function calls ¡ª useState is a new way to use the exact same capabilities that this.state provides in a class. Normally, variables ¡°disappear¡± when the function exits but state variables are preserved by React. What do we pass to useState as an argument? The only argument to the useState() Hook is the initial state. Unlike with classes, the state doesn't have to be an object. We can keep a number or a string if that's all we need. In our example, we just want a number for how many times the user clicked, so pass 0 as initial state for our variable. (If we wanted to store two different values in state, we would call useState() twice.) What does useState return? It returns a pair of values: the current state and a function that updates it. This is why we write const [count, setCount] = useState(). This is similar to this.state.count and this.setState in a class, except you get them in a pair. If you're not familiar with the syntax we used, we'll come back to it at the bottom of this page. Now that we know what the useState Hook does, our example should make more sense: import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); We declare a state variable called count, and set it to 0. React will remember its current value between re-renders, and provide the most recent one to our function. If we want to update the current count, we can call setCount.
Note You might be wondering: why is useState not named createState instead? ¡°Create¡± wouldn't be quite accurate because the state is only created the first time our component renders. During the next renders, useState gives us the current state. Otherwise it wouldn't be ¡°state¡± at all! There's also a reason why Hook names always start with use. We'll learn why later in the Rules of Hooks.

Reading State

When we want to display the current count in a class, we read this.state.count: <p>You clicked {this.state.count} times</p> In a function, we can use count directly: <p>You clicked {count} times</p>

Updating State

In a class, we need to call this.setState() to update the count state: <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> In a function, we already have setCount and count as variables so we don't need this: <button onClick={() => setCount(count + 1)}> Click me </button>

Recap

Let's now recap what we learned line by line and check our understanding. 1: import React, { useState } from 'react'; 2: 3: function Example() { 4: const [count, setCount] = useState(0); 5: 6: return ( 7: <div> 8: <p>You clicked {count} times</p> 9: <button onClick={() => setCount(count + 1)}>10: Click me 11: </button> 12: </div> 13: ); 14: }
  • Line 1: We import the useState Hook from React. It lets us keep local state in a function component.
  • Line 4: Inside the Example component, we declare a new state variable by calling the useState Hook. It returns a pair of values, to which we give names. We're calling our variable count because it holds the number of button clicks. We initialize it to zero by passing 0 as the only useState argument. The second returned item is itself a function. It lets us update the count so we'll name it setCount.
  • Line 9: When the user clicks, we call setCount with a new value. React will then re-render the Example component, passing the new count value to it.
This might seem like a lot to take in at first. Don't rush it! If you're lost in the explanation, look at the code above again and try to read it from top to bottom. We promise that once you try to ¡°forget¡± how state works in classes, and look at this code with fresh eyes, it will make sense.

Tip: What Do Square Brackets Mean?

You might have noticed the square brackets when we declare a state variable: const [count, setCount] = useState(0); The names on the left aren't a part of the React API. You can name your own state variables: const [fruit, setFruit] = useState('banana'); This JavaScript syntax is called ¡°array destructuring¡±. It means that we're making two new variables fruit and setFruit, where fruit is set to the first value returned by useState, and setFruit is the second. It is equivalent to this code: var fruitStateVariable = useState('banana'); // Returns a pair var fruit = fruitStateVariable[0]; // First item in a pair var setFruit = fruitStateVariable[1]; // Second item in a pair When we declare a state variable with useState, it returns a pair ¡ª an array with two items. The first item is the current value, and the second is a function that lets us update it. Using [0] and [1] to access them is a bit confusing because they have a specific meaning. This is why we use array destructuring instead.
Note You might be curious how React knows which component useState corresponds to since we're not passing anything like this back to React. We'll answer this question and many others in the FAQ section.

Tip: Using Multiple State Variables

Declaring state variables as a pair of [something, setSomething] is also handy because it lets us give different names to different state variables if we want to use more than one: function ExampleWithManyStates() { // Declare multiple state variables! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); In the above component, we have age, fruit, and todos as local variables, and we can update them individually: function handleOrangeClick() { // Similar to this.setState({ fruit: 'orange' }) setFruit('orange'); } You don't have to use many state variables. State variables can hold objects and arrays just fine, so you can still group related data together. However, unlike this.setState in a class, updating a state variable always replaces it instead of merging it. We provide more recommendations on splitting independent state variables in the FAQ.

Next Steps

On this page we've learned about one of the Hooks provided by React, called useState. We're also sometimes going to refer to it as the ¡°State Hook¡±. It lets us add local state to React function components ¡ª which we did for the first time ever! We also learned a little bit more about what Hooks are. Hooks are functions that let you ¡°hook into¡± React features from function components. Their names always start with use, and there are more Hooks we haven't seen yet. Now let's continue by learning the next Hook: useEffect. It lets you perform side effects in components, and is similar to lifecycle methods in classes.

Rules of Hooks

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. Hooks are JavaScript functions, but you need to follow two rules when using them. We provide a linter plugin to enforce these rules automatically:

Only Call Hooks at the Top Level

Don't call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That's what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls. (If you're curious, we'll explain this in depth below.)

Only Call Hooks from React Functions

Don't call Hooks from regular JavaScript functions. Instead, you can:
  • Call Hooks from React function components.
  • Call Hooks from custom Hooks (we'll learn about them on the next page).
By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.

ESLint Plugin

We released an ESLint plugin called eslint-plugin-react-hooks that enforces these two rules. You can add this plugin to your project if you'd like to try it: This plugin is included by default in Create React App. npm install eslint-plugin-react-hooks --save-dev // Your ESLint configuration { "plugins": [ // ... "react-hooks" ], "rules": { // ... "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies } } You can skip to the next page explaining how to write your own Hooks now. On this page, we'll continue by explaining the reasoning behind these rules.

Explanation

As we learned earlier, we can use multiple State or Effect Hooks in a single component: function Form() { // 1. Use the name state variable const [name, setName] = useState('Mary'); // 2. Use an effect for persisting the form useEffect(function persistForm() { localStorage.setItem('formData', name); }); // 3. Use the surname state variable const [surname, setSurname] = useState('Poppins'); // 4. Use an effect for updating the title useEffect(function updateTitle() { document.title = name + ' ' + surname; }); // ... } So how does React know which state corresponds to which useState call? The answer is that React relies on the order in which Hooks are called. Our example works because the order of the Hook calls is the same on every render: // ------------ // First render // ------------ useState('Mary') // 1. Initialize the name state variable with 'Mary' useEffect(persistForm) // 2. Add an effect for persisting the form useState('Poppins') // 3. Initialize the surname state variable with 'Poppins' useEffect(updateTitle) // 4. Add an effect for updating the title // ------------- // Second render // ------------- useState('Mary') // 1. Read the name state variable (argument is ignored) useEffect(persistForm) // 2. Replace the effect for persisting the form useState('Poppins') // 3. Read the surname state variable (argument is ignored) useEffect(updateTitle) // 4. Replace the effect for updating the title // ... As long as the order of the Hook calls is the same between renders, React can associate some local state with each of them. But what happens if we put a Hook call (for example, the persistForm effect) inside a condition? // We're breaking the first rule by using a Hook in a condition if (name !== '') { useEffect(function persistForm() { localStorage.setItem('formData', name); }); } The name !== '' condition is true on the first render, so we run this Hook. However, on the next render the user might clear the form, making the condition false. Now that we skip this Hook during rendering, the order of the Hook calls becomes different: useState('Mary') // 1. Read the name state variable (argument is ignored) // useEffect(persistForm) // This Hook was skipped! useState('Poppins') // 2 (but was 3). Fail to read the surname state variable useEffect(updateTitle) // 3 (but was 4). Fail to replace the effect React wouldn't know what to return for the second useState Hook call. React expected that the second Hook call in this component corresponds to the persistForm effect, just like during the previous render, but it doesn't anymore. From that point, every next Hook call after the one we skipped would also shift by one, leading to bugs. This is why Hooks must be called on the top level of our components. If we want to run an effect conditionally, we can put that condition inside our Hook: useEffect(function persistForm() { // We're not breaking the first rule anymore if (name !== '') { localStorage.setItem('formData', name); } }); Note that you don't need to worry about this problem if you use the provided lint rule. But now you also know why Hooks work this way, and which issues the rule is preventing.

Next Steps

Finally, we're ready to learn about writing your own Hooks! Custom Hooks let you combine Hooks provided by React into your own abstractions, and reuse common stateful logic between different components.

Building Your Own Hooks

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. Building your own Hooks lets you extract component logic into reusable functions. When we were learning about using the Effect Hook, we saw this component from a chat application that displays a message indicating whether a friend is online or offline: import React, { useState, useEffect } from 'react'; function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; } Now let's say that our chat application also has a contact list, and we want to render names of online users with a green color. We could copy and paste similar logic above into our FriendListItem component but it wouldn't be ideal: import React, { useState, useEffect } from 'react'; function FriendListItem(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li> ); } Instead, we'd like to share this logic between FriendStatus and FriendListItem. Traditionally in React, we've had two popular ways to share stateful logic between components: render props and higher-order components. We will now look at how Hooks solve many of the same problems without forcing you to add more components to the tree.

Extracting a Custom Hook

When we want to share logic between two JavaScript functions, we extract it to a third function. Both components and Hooks are functions, so this works for them too! A custom Hook is a JavaScript function whose name starts with ¡±use¡± and that may call other Hooks. For example, useFriendStatus below is our first custom Hook: import { useState, useEffect } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; } There's nothing new inside of it ¡ª the logic is copied from the components above. Just like in a component, make sure to only call other Hooks unconditionally at the top level of your custom Hook. Unlike a React component, a custom Hook doesn't need to have a specific signature. We can decide what it takes as arguments, and what, if anything, it should return. In other words, it's just like a normal function. Its name should always start with use so that you can tell at a glance that the rules of Hooks apply to it. The purpose of our useFriendStatus Hook is to subscribe us to a friend's status. This is why it takes friendID as an argument, and returns whether this friend is online: function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // ... return isOnline; } Now let's see how we can use our custom Hook.

Using a Custom Hook

In the beginning, our stated goal was to remove the duplicated logic from the FriendStatus and FriendListItem components. Both of them want to know whether a friend is online. Now that we've extracted this logic to a useFriendStatus hook, we can just use it: function FriendStatus(props) { const isOnline = useFriendStatus(props.friend.id); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; } function FriendListItem(props) { const isOnline = useFriendStatus(props.friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li> ); } Is this code equivalent to the original examples? Yes, it works in exactly the same way. If you look closely, you'll notice we didn't make any changes to the behavior. All we did was to extract some common code between two functions into a separate function. Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature. Do I have to name my custom Hooks starting with ¡°use¡±? Please do. This convention is very important. Without it, we wouldn't be able to automatically check for violations of rules of Hooks because we couldn't tell if a certain function contains calls to Hooks inside of it. Do two components using the same Hook share state? No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated. How does a custom Hook get isolated state? Each call to a Hook gets isolated state. Because we call useFriendStatus directly, from React's point of view our component just calls useState and useEffect. And as we learned earlier, we can call useState and useEffect many times in one component, and they will be completely independent.

Tip: Pass Information Between Hooks

Since Hooks are functions, we can pass information between them. To illustrate this, we'll use another component from our hypothetical chat example. This is a chat message recipient picker that displays whether the currently selected friend is online: const friendList = [ { id: 1, name: 'Phoebe' }, { id: 2, name: 'Rachel' }, { id: 3, name: 'Ross' }, ]; function ChatRecipientPicker() { const [recipientID, setRecipientID] = useState(1); const isRecipientOnline = useFriendStatus(recipientID); return ( <> <Circle color={isRecipientOnline ? 'green' : 'red'} /> <select value={recipientID} onChange={e => setRecipientID(Number(e.target.value))} > {friendList.map(friend => ( <option key={friend.id} value={friend.id}> {friend.name} </option> ))} </select> </> ); } We keep the currently chosen friend ID in the recipientID state variable, and update it if the user chooses a different friend in the <select> picker. Because the useState Hook call gives us the latest value of the recipientID state variable, we can pass it to our custom useFriendStatus Hook as an argument: const [recipientID, setRecipientID] = useState(1); const isRecipientOnline = useFriendStatus(recipientID); This lets us know whether the currently selected friend is online. If we pick a different friend and update the recipientID state variable, our useFriendStatus Hook will unsubscribe from the previously selected friend, and subscribe to the status of the newly selected one.

useYourImagination()

Custom Hooks offer the flexibility of sharing logic that wasn't possible in React components before. You can write custom Hooks that cover a wide range of use cases like form handling, animation, declarative subscriptions, timers, and probably many more we haven't considered. What's more, you can build Hooks that are just as easy to use as React's built-in features. Try to resist adding abstraction too early. Now that function components can do more, it's likely that the average function component in your codebase will become longer. This is normal ¡ª don't feel like you have to immediately split it into Hooks. But we also encourage you to start spotting cases where a custom Hook could hide complex logic behind a simple interface, or help untangle a messy component. For example, maybe you have a complex component that contains a lot of local state that is managed in an ad-hoc way. useState doesn't make centralizing the update logic any easier so you might prefer to write it as a Redux reducer: function todosReducer(state, action) { switch (action.type) { case 'add': return [...state, { text: action.text, completed: false }]; // ... other actions ... default: return state; } } Reducers are very convenient to test in isolation, and scale to express complex update logic. You can further break them apart into smaller reducers if necessary. However, you might also enjoy the benefits of using React local state, or might not want to install another library. So what if we could write a useReducer Hook that lets us manage the local state of our component with a reducer? A simplified version of it might look like this: function useReducer(reducer, initialState) { const [state, setState] = useState(initialState); function dispatch(action) { const nextState = reducer(state, action); setState(nextState); } return [state, dispatch]; } Now we could use it in our component, and let the reducer drive its state management: function Todos() { const [todos, dispatch] = useReducer(todosReducer, []); function handleAddClick(text) { dispatch({ type: 'add', text }); } // ... } The need to manage local state with a reducer in a complex component is common enough that we've built the useReducer Hook right into React. You'll find it together with other built-in Hooks in the Hooks API reference.

Hooks API Reference

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. This page describes the APIs for the built-in Hooks in React. If you're new to Hooks, you might want to check out the overview first. You may also find useful information in the frequently asked questions section.
  • Basic Hooks
    • useState
    • useEffect
    • useContext
  • Additional Hooks
    • useReducer
    • useCallback
    • useMemo
    • useRef
    • useImperativeHandle
    • useLayoutEffect
    • useDebugValue

Basic Hooks

useState

const [state, setState] = useState(initialState); Returns a stateful value, and a function to update it. During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState). The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component. setState(newState); During subsequent re-renders, the first value returned by useState will always be the most recent state after applying updates.
Note React guarantees that setState function identity is stable and won't change on re-renders. This is why it's safe to omit from the useEffect or useCallback dependency list.
Functional updates
If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value. Here's an example of a counter component that uses both forms of setState: function Counter({initialCount}) { const [count, setCount] = useState(initialCount); return ( <> Count: {count} <button onClick={() => setCount(initialCount)}>Reset</button> <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button> <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button> </> ); } The ¡±+¡± and ¡±-¡± buttons use the functional form, because the updated value is based on the previous value. But the ¡°Reset¡± button uses the normal form, because it always sets the count back to the initial value. If your update function returns the exact same value as the current state, the subsequent rerender will be skipped completely.
Note Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax: setState(prevState => { // Object.assign would also work return {...prevState, ...updatedValues}; }); Another option is useReducer, which is more suited for managing state objects that contain multiple sub-values.
Lazy initial state
The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render: const [state, setState] = useState(() => { const initialState = someExpensiveComputation(props); return initialState; });
Bailing out of a state update
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.) Note that React may still need to render that specific component again before bailing out. That shouldn't be a concern because React won't unnecessarily go ¡°deeper¡± into the tree. If you're doing expensive calculations while rendering, you can optimize them with useMemo.

useEffect

useEffect(didUpdate); Accepts a function that contains imperative, possibly effectful code. Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React's render phase). Doing so will lead to confusing bugs and inconsistencies in the UI. Instead, use useEffect. The function passed to useEffect will run after the render is committed to the screen. Think of effects as an escape hatch from React's purely functional world into the imperative world. By default, effects run after every completed render, but you can choose to fire them only when certain values have changed.
Cleaning up an effect
Often, effects create resources that need to be cleaned up before the component leaves the screen, such as a subscription or timer ID. To do this, the function passed to useEffect may return a clean-up function. For example, to create a subscription: useEffect(() => { const subscription = props.source.subscribe(); return () => { // Clean up the subscription subscription.unsubscribe(); }; }); The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect. In our example, this means a new subscription is created on every update. To avoid firing an effect on every update, refer to the next section.
Timing of effects
Unlike componentDidMount and componentDidUpdate, the function passed to useEffect fires after layout and paint, during a deferred event. This makes it suitable for the many common side effects, like setting up subscriptions and event handlers, because most types of work shouldn't block the browser from updating the screen. However, not all effects can be deferred. For example, a DOM mutation that is visible to the user must fire synchronously before the next paint so that the user does not perceive a visual inconsistency. (The distinction is conceptually similar to passive versus active event listeners.) For these types of effects, React provides one additional Hook called useLayoutEffect. It has the same signature as useEffect, and only differs in when it is fired. Although useEffect is deferred until after the browser has painted, it's guaranteed to fire before any new renders. React will always flush a previous render's effects before starting a new update.
Conditionally firing an effect
The default behavior for effects is to fire the effect after every completed render. That way an effect is always recreated if one of its dependencies changes. However, this may be overkill in some cases, like the subscription example from the previous section. We don't need to create a new subscription on every update, only if the source prop has changed. To implement this, pass a second argument to useEffect that is the array of values that the effect depends on. Our updated example now looks like this: useEffect( () => { const subscription = props.source.subscribe(); return () => { subscription.unsubscribe(); }; }, [props.source], ); Now the subscription will only be recreated when props.source changes.
Note If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders. Learn more about how to deal with functions and what to do when the array values change too often. If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn't depend on any values from props or state, so it never needs to re-run. This isn't handled as a special case ¡ª it follows directly from how the dependencies array always works. If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often. Also, don't forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem. We recommend using the exhaustive-deps rule as part of our eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.
The array of dependencies is not passed as arguments to the effect function. Conceptually, though, that's what they represent: every value referenced inside the effect function should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically.

useContext

const value = useContext(MyContext); Accepts a context object (the value returned from React.createContext) and returns the current context value for that context. The current context value is determined by the value prop of the nearest <MyContext.Provider> above the calling component in the tree. When the nearest <MyContext.Provider> above the component updates, this Hook will trigger a rerender with the latest context value passed to that MyContext provider. Even if an ancestor uses React.memo or shouldComponentUpdate, a rerender will still happen starting at the component itself using useContext. Don't forget that the argument to useContext must be the context object itself:
  • Correct: useContext(MyContext)
  • Incorrect: useContext(MyContext.Consumer)
  • Incorrect: useContext(MyContext.Provider)
A component calling useContext will always re-render when the context value changes. If re-rendering the component is expensive, you can optimize it by using memoization.
Tip If you're familiar with the context API before Hooks, useContext(MyContext) is equivalent to static contextType = MyContext in a class, or to <MyContext.Consumer>. useContext(MyContext) only lets you read the context and subscribe to its changes. You still need a <MyContext.Provider> above in the tree to provide the value for this context.
Putting it together with Context.Provider const themes = { light: { foreground: "#000000", background: "#eeeeee" }, dark: { foreground: "#ffffff", background: "#222222" } }; const ThemeContext = React.createContext(themes.light); function App() { return ( <ThemeContext.Provider value={themes.dark}> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar(props) { return ( <div> <ThemedButton /> </div> ); } function ThemedButton() { const theme = useContext(ThemeContext); return ( <button style={{ background: theme.background, color: theme.foreground }}> I am styled by theme context! </button> ); } This example is modified for hooks from a previous example in the Context Advanced Guide, where you can find more information about when and how to use Context.

Additional Hooks

The following Hooks are either variants of the basic ones from the previous section, or only needed for specific edge cases. Don't stress about learning them up front.

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init); An alternative to useState. Accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method. (If you're familiar with Redux, you already know how this works.) useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one. useReducer also lets you optimize performance for components that trigger deep updates because you can pass dispatch down instead of callbacks. Here's the counter example from the useState section, rewritten to use a reducer: const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: throw new Error(); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'decrement'})}>-</button> <button onClick={() => dispatch({type: 'increment'})}>+</button> </> ); }
Note React guarantees that dispatch function identity is stable and won't change on re-renders. This is why it's safe to omit from the useEffect or useCallback dependency list.
Specifying the initial state
There are two different ways to initialize useReducer state. You may choose either one depending on the use case. The simplest way is to pass the initial state as a second argument: const [state, dispatch] = useReducer( reducer, {count: initialCount} );
Note React doesn't use the state = initialState argument convention popularized by Redux. The initial value sometimes needs to depend on props and so is specified from the Hook call instead. If you feel strongly about this, you can call useReducer(reducer, undefined, reducer) to emulate the Redux behavior, but it's not encouraged.
Lazy initialization
You can also create the initial state lazily. To do this, you can pass an init function as the third argument. The initial state will be set to init(initialArg). It lets you extract the logic for calculating the initial state outside the reducer. This is also handy for resetting the state later in response to an action: function init(initialCount) { return {count: initialCount};} function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; case 'reset': return init(action.payload); default: throw new Error(); } } function Counter({initialCount}) { const [state, dispatch] = useReducer(reducer, initialCount, init); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'reset', payload: initialCount})}> Reset </button> <button onClick={() => dispatch({type: 'decrement'})}>-</button> <button onClick={() => dispatch({type: 'increment'})}>+</button> </> ); }
Bailing out of a dispatch
If you return the same value from a Reducer Hook as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.) Note that React may still need to render that specific component again before bailing out. That shouldn't be a concern because React won't unnecessarily go ¡°deeper¡± into the tree. If you're doing expensive calculations while rendering, you can optimize them with useMemo.

useCallback

const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], ); Returns a memoized callback. Pass an inline callback and an array of dependencies. useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate). useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).
Note The array of dependencies is not passed as arguments to the callback. Conceptually, though, that's what they represent: every value referenced inside the callback should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically. We recommend using the exhaustive-deps rule as part of our eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); Returns a memoized value. Pass a ¡°create¡± function and an array of dependencies. useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render. Remember that the function passed to useMemo runs during rendering. Don't do anything there that you wouldn't normally do while rendering. For example, side effects belong in useEffect, not useMemo. If no array is provided, a new value will be computed on every render. You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to ¡°forget¡± some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo ¡ª and then add it to optimize performance.
Note The array of dependencies is not passed as arguments to the function. Conceptually, though, that's what they represent: every value referenced inside the function should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically. We recommend using the exhaustive-deps rule as part of our eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.

useRef

const refContainer = useRef(initialValue); useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component. A common use case is to access a child imperatively: function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { // `current` points to the mounted text input element inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button> </> ); } Essentially, useRef is like a ¡°box¡± that can hold a mutable value in its .current property. You might be familiar with refs primarily as a way to access the DOM. If you pass a ref object to React with <div ref={myRef} />, React will set its .current property to the corresponding DOM node whenever that node changes. However, useRef() is useful for more than the ref attribute. It's handy for keeping any mutable value around similar to how you'd use instance fields in classes. This works because useRef() creates a plain JavaScript object. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render. Keep in mind that useRef doesn't notify you when its content changes. Mutating the .current property doesn't cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps]) useImperativeHandle customizes the instance value that is exposed to parent components when using ref. As always, imperative code using refs should be avoided in most cases. useImperativeHandle should be used with forwardRef: function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} ... />; } FancyInput = forwardRef(FancyInput); In this example, a parent component that renders <FancyInput ref={inputRef} /> would be able to call inputRef.current.focus().

useLayoutEffect

The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint. Prefer the standard useEffect when possible to avoid blocking visual updates.
Tip If you're migrating code from a class component, note useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate. However, we recommend starting with useEffect first and only trying useLayoutEffect if that causes a problem. If you use server rendering, keep in mind that neither useLayoutEffect nor useEffect can run until the JavaScript is downloaded. This is why React warns when a server-rendered component contains useLayoutEffect. To fix this, either move that logic to useEffect (if it isn't necessary for the first render), or delay showing that component until after the client renders (if the HTML looks broken until useLayoutEffect runs). To exclude a component that needs layout effects from the server-rendered HTML, render it conditionally with showChild && <Child /> and defer showing it with useEffect(() => { setShowChild(true); }, []). This way, the UI doesn't appear broken before hydration.

useDebugValue

useDebugValue(value) useDebugValue can be used to display a label for custom hooks in React DevTools. For example, consider the useFriendStatus custom Hook described in ¡°Building Your Own Hooks¡±: function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // ... // Show a label in DevTools next to this Hook // e.g. "FriendStatus: Online" useDebugValue(isOnline ? 'Online' : 'Offline'); return isOnline; }
Tip We don't recommend adding debug values to every custom Hook. It's most valuable for custom Hooks that are part of shared libraries.
Defer formatting debug values
In some cases formatting a value for display might be an expensive operation. It's also unnecessary unless a Hook is actually inspected. For this reason useDebugValue accepts a formatting function as an optional second parameter. This function is only called if the Hooks are inspected. It receives the debug value as a parameter and should return a formatted display value. For example a custom Hook that returned a Date value could avoid calling the toDateString function unnecessarily by passing the following formatter: useDebugValue(date, date => date.toDateString());

Hooks FAQ

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. This page answers some of the frequently asked questions about Hooks.
  • Adoption Strategy
    • Which versions of React include Hooks?
    • Do I need to rewrite all my class components?
    • What can I do with Hooks that I couldn't with classes?
    • How much of my React knowledge stays relevant?
    • Should I use Hooks, classes, or a mix of both?
    • Do Hooks cover all use cases for classes?
    • Do Hooks replace render props and higher-order components?
    • What do Hooks mean for popular APIs like Redux connect() and React Router?
    • Do Hooks work with static typing?
    • How to test components that use Hooks?
    • What exactly do the lint rules enforce?
  • From Classes to Hooks
    • How do lifecycle methods correspond to Hooks?
    • How can I do data fetching with Hooks?
    • Is there something like instance variables?
    • Should I use one or many state variables?
    • Can I run an effect only on updates?
    • How to get the previous props or state?
    • Why am I seeing stale props or state inside my function?
    • How do I implement getDerivedStateFromProps?
    • Is there something like forceUpdate?
    • Can I make a ref to a function component?
    • How can I measure a DOM node?
    • What does const [thing, setThing] = useState() mean?
  • Performance Optimizations
    • Can I skip an effect on updates?
    • Is it safe to omit functions from the list of dependencies?
    • What can I do if my effect dependencies change too often?
    • How do I implement shouldComponentUpdate?
    • How to memoize calculations?
    • How to create expensive objects lazily?
    • Are Hooks slow because of creating functions in render?
    • How to avoid passing callbacks down?
    • How to read an often-changing value from useCallback?
  • Under the Hood
    • How does React associate Hook calls with components?
    • What is the prior art for Hooks?

Adoption Strategy

Which versions of React include Hooks?

Starting with 16.8.0, React includes a stable implementation of React Hooks for:
  • React DOM
  • React Native
  • React DOM Server
  • React Test Renderer
  • React Shallow Renderer
Note that to enable Hooks, all React packages need to be 16.8.0 or higher. Hooks won't work if you forget to update, for example, React DOM. React Native 0.59 and above support Hooks.

Do I need to rewrite all my class components?

No. There are no plans to remove classes from React ¡ª we all need to keep shipping products and can't afford rewrites. We recommend trying Hooks in new code.

What can I do with Hooks that I couldn't with classes?

Hooks offer a powerful and expressive new way to reuse functionality between components. ¡°Building Your Own Hooks¡± provides a glimpse of what's possible. This article by a React core team member dives deeper into the new capabilities unlocked by Hooks.

How much of my React knowledge stays relevant?

Hooks are a more direct way to use the React features you already know ¡ª such as state, lifecycle, context, and refs. They don't fundamentally change how React works, and your knowledge of components, props, and top-down data flow is just as relevant. Hooks do have a learning curve of their own. If there's something missing in this documentation, raise an issue and we'll try to help.

Should I use Hooks, classes, or a mix of both?

When you're ready, we'd encourage you to start trying Hooks in new components you write. Make sure everyone on your team is on board with using them and familiar with this documentation. We don't recommend rewriting your existing classes to Hooks unless you planned to rewrite them anyway (e.g. to fix bugs). You can't use Hooks inside a class component, but you can definitely mix classes and function components with Hooks in a single tree. Whether a component is a class or a function that uses Hooks is an implementation detail of that component. In the longer term, we expect Hooks to be the primary way people write React components.

Do Hooks cover all use cases for classes?

Our goal is for Hooks to cover all use cases for classes as soon as possible. There are no Hook equivalents to the uncommon getSnapshotBeforeUpdate, getDerivedStateFromError and componentDidCatch lifecycles yet, but we plan to add them soon. It is an early time for Hooks, and some third-party libraries might not be compatible with Hooks at the moment.

Do Hooks replace render props and higher-order components?

Often, render props and higher-order components render only a single child. We think Hooks are a simpler way to serve this use case. There is still a place for both patterns (for example, a virtual scroller component might have a renderItem prop, or a visual container component might have its own DOM structure). But in most cases, Hooks will be sufficient and can help reduce nesting in your tree.

What do Hooks mean for popular APIs like Redux connect() and React Router?

You can continue to use the exact same APIs as you always have; they'll continue to work. React Redux since v7.1.0 supports Hooks API and exposes hooks like useDispatch or useSelector. React Router supports hooks since v5.1. Other libraries might support hooks in the future too.

Do Hooks work with static typing?

Hooks were designed with static typing in mind. Because they're functions, they are easier to type correctly than patterns like higher-order components. The latest Flow and TypeScript React definitions include support for React Hooks. Importantly, custom Hooks give you the power to constrain React API if you'd like to type them more strictly in some way. React gives you the primitives, but you can combine them in different ways than what we provide out of the box.

How to test components that use Hooks?

From React's point of view, a component using Hooks is just a regular component. If your testing solution doesn't rely on React internals, testing components with Hooks shouldn't be different from how you normally test components.
Note Testing Recipes include many examples that you can copy and paste.
For example, let's say we have this counter component: function Example() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } We'll test it using React DOM. To make sure that the behavior matches what happens in the browser, we'll wrap the code rendering and updating it into ReactTestUtils.act() calls: import React from 'react'; import ReactDOM from 'react-dom'; import { act } from 'react-dom/test-utils';import Counter from './Counter'; let container; beforeEach(() => { container = document.createElement('div'); document.body.appendChild(container); }); afterEach(() => { document.body.removeChild(container); container = null; }); it('can render and update a counter', () => { // Test first render and effect act(() => { ReactDOM.render(<Counter />, container); }); const button = container.querySelector('button'); const label = container.querySelector('p'); expect(label.textContent).toBe('You clicked 0 times'); expect(document.title).toBe('You clicked 0 times'); // Test second render and effect act(() => { button.dispatchEvent(new MouseEvent('click', {bubbles: true})); }); expect(label.textContent).toBe('You clicked 1 times'); expect(document.title).toBe('You clicked 1 times'); }); The calls to act() will also flush the effects inside of them. If you need to test a custom Hook, you can do so by creating a component in your test, and using your Hook from it. Then you can test the component you wrote. To reduce the boilerplate, we recommend using React Testing Library which is designed to encourage writing tests that use your components as the end users do. For more information, check out Testing Recipes.

What exactly do the lint rules enforce?

We provide an ESLint plugin that enforces rules of Hooks to avoid bugs. It assumes that any function starting with ¡±use¡± and a capital letter right after it is a Hook. We recognize this heuristic isn't perfect and there may be some false positives, but without an ecosystem-wide convention there is just no way to make Hooks work well ¡ª and longer names will discourage people from either adopting Hooks or following the convention. In particular, the rule enforces that:
  • Calls to Hooks are either inside a PascalCase function (assumed to be a component) or another useSomething function (assumed to be a custom Hook).
  • Hooks are called in the same order on every render.
There are a few more heuristics, and they might change over time as we fine-tune the rule to balance finding bugs with avoiding false positives.

From Classes to Hooks

How do lifecycle methods correspond to Hooks?

  • constructor: Function components don't need a constructor. You can initialize the state in the useState call. If computing the initial state is expensive, you can pass a function to useState.
  • getDerivedStateFromProps: Schedule an update while rendering instead.
  • shouldComponentUpdate: See React.memo below.
  • render: This is the function component body itself.
  • componentDidMount, componentDidUpdate, componentWillUnmount: The useEffect Hook can express all combinations of these (including less common cases).
  • getSnapshotBeforeUpdate, componentDidCatch and getDerivedStateFromError: There are no Hook equivalents for these methods yet, but they will be added soon.

How can I do data fetching with Hooks?

Here is a small demo to get you started. To learn more, check out this article about data fetching with Hooks.

Is there something like instance variables?

Yes! The useRef() Hook isn't just for DOM refs. The ¡°ref¡± object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class. You can write to it from inside useEffect: function Timer() { const intervalRef = useRef(); useEffect(() => { const id = setInterval(() => { // ... }); intervalRef.current = id; return () => { clearInterval(intervalRef.current); }; }); // ... } If we just wanted to set an interval, we wouldn't need the ref (id could be local to the effect), but it's useful if we want to clear the interval from an event handler: // ... function handleCancelClick() { clearInterval(intervalRef.current); } // ... Conceptually, you can think of refs as similar to instance variables in a class. Unless you're doing lazy initialization, avoid setting refs during rendering ¡ª this can lead to surprising behavior. Instead, typically you want to modify refs in event handlers and effects.

Should I use one or many state variables?

If you're coming from classes, you might be tempted to always call useState() once and put all state into a single object. You can do it if you'd like. Here is an example of a component that follows the mouse movement. We keep its position and size in the local state: function Box() { const [state, setState] = useState({ left: 0, top: 0, width: 100, height: 100 }); // ... } Now let's say we want to write some logic that changes left and top when the user moves their mouse. Note how we have to merge these fields into the previous state object manually: // ... useEffect(() => { function handleWindowMouseMove(e) { // Spreading "...state" ensures we don't "lose" width and height setState(state => ({ ...state, left: e.pageX, top: e.pageY })); } // Note: this implementation is a bit simplified window.addEventListener('mousemove', handleWindowMouseMove); return () => window.removeEventListener('mousemove', handleWindowMouseMove); }, []); // ... This is because when we update a state variable, we replace its value. This is different from this.setState in a class, which merges the updated fields into the object. If you miss automatic merging, you could write a custom useLegacyState Hook that merges object state updates. However, we recommend to split state into multiple state variables based on which values tend to change together. For example, we could split our component state into position and size objects, and always replace the position with no need for merging: function Box() { const [position, setPosition] = useState({ left: 0, top: 0 }); const [size, setSize] = useState({ width: 100, height: 100 }); useEffect(() => { function handleWindowMouseMove(e) { setPosition({ left: e.pageX, top: e.pageY }); } // ... Separating independent state variables also has another benefit. It makes it easy to later extract some related logic into a custom Hook, for example: function Box() { const position = useWindowPosition(); const [size, setSize] = useState({ width: 100, height: 100 }); // ... } function useWindowPosition() { const [position, setPosition] = useState({ left: 0, top: 0 }); useEffect(() => { // ... }, []); return position; } Note how we were able to move the useState call for the position state variable and the related effect into a custom Hook without changing their code. If all state was in a single object, extracting it would be more difficult. Both putting all state in a single useState call, and having a useState call per each field can work. Components tend to be most readable when you find a balance between these two extremes, and group related state into a few independent state variables. If the state logic becomes complex, we recommend managing it with a reducer or a custom Hook.

Can I run an effect only on updates?

This is a rare use case. If you need it, you can use a mutable ref to manually store a boolean value corresponding to whether you are on the first or a subsequent render, then check that flag in your effect. (If you find yourself doing this often, you could create a custom Hook for it.)

How to get the previous props or state?

Currently, you can do it manually with a ref: function Counter() { const [count, setCount] = useState(0); const prevCountRef = useRef(); useEffect(() => { prevCountRef.current = count; }); const prevCount = prevCountRef.current; return <h2>Now: {count}, before: {prevCount}</h2>; } This might be a bit convoluted but you can extract it into a custom Hook: function Counter() { const [count, setCount] = useState(0); const prevCount = usePrevious(count); return <h2>Now: {count}, before: {prevCount}</h2>; } function usePrevious(value) { const ref = useRef(); useEffect(() => { ref.current = value; }); return ref.current; } Note how this would work for props, state, or any other calculated value. function Counter() { const [count, setCount] = useState(0); const calculation = count + 100; const prevCalculation = usePrevious(calculation); // ... It's possible that in the future React will provide a usePrevious Hook out of the box since it's a relatively common use case. See also the recommended pattern for derived state.

Why am I seeing stale props or state inside my function?

Any function inside a component, including event handlers and effects, ¡°sees¡± the props and state from the render it was created in. For example, consider code like this: function Example() { const [count, setCount] = useState(0); function handleAlertClick() { setTimeout(() => { alert('You clicked on: ' + count); }, 3000); } return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> <button onClick={handleAlertClick}> Show alert </button> </div> ); } If you first click ¡°Show alert¡± and then increment the counter, the alert will show the count variable at the time you clicked the ¡°Show alert¡± button. This prevents bugs caused by the code assuming props and state don't change. If you intentionally want to read the latest state from some asynchronous callback, you could keep it in a ref, mutate it, and read from it. Finally, another possible reason you're seeing stale props or state is if you use the ¡°dependency array¡± optimization but didn't correctly specify all the dependencies. For example, if an effect specifies [] as the second argument but reads someProp inside, it will keep ¡°seeing¡± the initial value of someProp. The solution is to either remove the dependency array, or to fix it. Here's how you can deal with functions, and here's other common strategies to run effects less often without incorrectly skipping dependencies.
Note We provide an exhaustive-deps ESLint rule as a part of the eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.

How do I implement getDerivedStateFromProps?

While you probably don't need it, in rare cases that you do (such as implementing a <Transition> component), you can update the state right during rendering. React will re-run the component with updated state immediately after exiting the first render so it wouldn't be expensive. Here, we store the previous value of the row prop in a state variable so that we can compare: function ScrollView({row}) { const [isScrollingDown, setIsScrollingDown] = useState(false); const [prevRow, setPrevRow] = useState(null); if (row !== prevRow) { // Row changed since last render. Update isScrollingDown. setIsScrollingDown(prevRow !== null && row > prevRow); setPrevRow(row); } return `Scrolling down: ${isScrollingDown}`; } This might look strange at first, but an update during rendering is exactly what getDerivedStateFromProps has always been like conceptually.

Is there something like forceUpdate?

Both useState and useReducer Hooks bail out of updates if the next value is the same as the previous one. Mutating state in place and calling setState will not cause a re-render. Normally, you shouldn't mutate local state in React. However, as an escape hatch, you can use an incrementing counter to force a re-render even if the state has not changed: const [ignored, forceUpdate] = useReducer(x => x + 1, 0); function handleClick() { forceUpdate(); } Try to avoid this pattern if possible.

Can I make a ref to a function component?

While you shouldn't need this often, you may expose some imperative methods to a parent component with the useImperativeHandle Hook.

How can I measure a DOM node?

One rudimentary way to measure the position or size of a DOM node is to use a callback ref. React will call that callback whenever the ref gets attached to a different node. Here is a small demo: function MeasureExample() { const [height, setHeight] = useState(0); const measuredRef = useCallback(node => { if (node !== null) { setHeight(node.getBoundingClientRect().height); } }, []); return ( <> <h2 ref={measuredRef}>Hello, world</h2> <h3>The above header is {Math.round(height)}px tall</h3> </> ); } We didn't choose useRef in this example because an object ref doesn't notify us about changes to the current ref value. Using a callback ref ensures that even if a child component displays the measured node later (e.g. in response to a click), we still get notified about it in the parent component and can update the measurements. Note that we pass [] as a dependency array to useCallback. This ensures that our ref callback doesn't change between the re-renders, and so React won't call it unnecessarily. In this example, the callback ref will be called only when the component mounts and unmounts, since the rendered <h2> component stays present throughout any rerenders. If you want to be notified any time a component resizes, you may want to use ResizeObserver or a third-party Hook built on it. If you want, you can extract this logic into a reusable Hook: function MeasureExample() { const [rect, ref] = useClientRect(); return ( <> <h2 ref={ref}>Hello, world</h2> {rect !== null && <h3>The above header is {Math.round(rect.height)}px tall</h3> } </> ); } function useClientRect() { const [rect, setRect] = useState(null); const ref = useCallback(node => { if (node !== null) { setRect(node.getBoundingClientRect()); } }, []); return [rect, ref]; }

What does const [thing, setThing] = useState() mean?

If you're not familiar with this syntax, check out the explanation in the State Hook documentation.

Performance Optimizations

Can I skip an effect on updates?

Yes. See conditionally firing an effect. Note that forgetting to handle updates often introduces bugs, which is why this isn't the default behavior.

Is it safe to omit functions from the list of dependencies?

Generally speaking, no. function Example({ someProp }) { function doSomething() { console.log(someProp); } useEffect(() => { doSomething(); }, []); // This is not safe (it calls `doSomething` which uses `someProp`)} It's difficult to remember which props or state are used by functions outside of the effect. This is why usually you'll want to declare functions needed by an effect inside of it. Then it's easy to see what values from the component scope that effect depends on: function Example({ someProp }) { useEffect(() => { function doSomething() { console.log(someProp); } doSomething(); }, [someProp]); // OK (our effect only uses `someProp`)} If after that we still don't use any values from the component scope, it's safe to specify []: useEffect(() => { function doSomething() { console.log('hello'); } doSomething(); }, []); // OK in this example because we don't use *any* values from component scope Depending on your use case, there are a few more options described below.
Note We provide the exhaustive-deps ESLint rule as a part of the eslint-plugin-react-hooks package. It helps you find components that don't handle updates consistently.
Let's see why this matters. If you specify a list of dependencies as the last argument to useEffect, useLayoutEffect, useMemo, useCallback, or useImperativeHandle, it must include all values that are used inside the callback and participate in the React data flow. That includes props, state, and anything derived from them. It is only safe to omit a function from the dependency list if nothing in it (or the functions called by it) references props, state, or values derived from them. This example has a bug: function ProductPage({ productId }) { const [product, setProduct] = useState(null); async function fetchProduct() { const response = await fetch('http://myapi/product/' + productId); // Uses productId prop const json = await response.json(); setProduct(json); } useEffect(() => { fetchProduct(); }, []); // Invalid because `fetchProduct` uses `productId` // ... } The recommended fix is to move that function inside of your effect. That makes it easy to see which props or state your effect uses, and to ensure they're all declared: function ProductPage({ productId }) { const [product, setProduct] = useState(null); useEffect(() => { // By moving this function inside the effect, we can clearly see the values it uses. async function fetchProduct() { const response = await fetch('http://myapi/product/' + productId); const json = await response.json(); setProduct(json); } fetchProduct(); }, [productId]); // Valid because our effect only uses productId // ... } This also allows you to handle out-of-order responses with a local variable inside the effect: useEffect(() => { let ignore = false; async function fetchProduct() { const response = await fetch('http://myapi/product/' + productId); const json = await response.json(); if (!ignore) setProduct(json); } fetchProduct(); return () => { ignore = true }; }, [productId]); We moved the function inside the effect so it doesn't need to be in its dependency list.
Tip Check out this small demo and this article to learn more about data fetching with Hooks.
If for some reason you can't move a function inside an effect, there are a few more options:
  • You can try moving that function outside of your component. In that case, the function is guaranteed to not reference any props or state, and also doesn't need to be in the list of dependencies.
  • If the function you're calling is a pure computation and is safe to call while rendering, you may call it outside of the effect instead, and make the effect depend on the returned value.
  • As a last resort, you can add a function to effect dependencies but wrap its definition into the useCallback Hook. This ensures it doesn't change on every render unless its own dependencies also change:
function ProductPage({ productId }) { // Wrap with useCallback to avoid change on every render const fetchProduct = useCallback(() => { // ... Does something with productId ... }, [productId]); // All useCallback dependencies are specified return <ProductDetails fetchProduct={fetchProduct} />; } function ProductDetails({ fetchProduct }) { useEffect(() => { fetchProduct(); }, [fetchProduct]); // All useEffect dependencies are specified // ... } Note that in the above example we need to keep the function in the dependencies list. This ensures that a change in the productId prop of ProductPage automatically triggers a refetch in the ProductDetails component.

What can I do if my effect dependencies change too often?

Sometimes, your effect may be using state that changes too often. You might be tempted to omit that state from a list of dependencies, but that usually leads to bugs: function Counter() { const [count, setCount] = useState(0); useEffect(() => { const id = setInterval(() => { setCount(count + 1); // This effect depends on the `count` state }, 1000); return () => clearInterval(id); }, []); // Bug: `count` is not specified as a dependency return <h2>{count}</h2>; } The empty set of dependencies, [], means that the effect will only run once when the component mounts, and not on every re-render. The problem is that inside the setInterval callback, the value of count does not change, because we've created a closure with the value of count set to 0 as it was when the effect callback ran. Every second, this callback then calls setCount(0 + 1), so the count never goes above 1. Specifying [count] as a list of dependencies would fix the bug, but would cause the interval to be reset on every change. Effectively, each setInterval would get one chance to execute before being cleared (similar to a setTimeout.) That may not be desirable. To fix this, we can use the functional update form of setState. It lets us specify how the state needs to change without referencing the current state: function Counter() { const [count, setCount] = useState(0); useEffect(() => { const id = setInterval(() => { setCount(c => c + 1); // This doesn't depend on `count` variable outside }, 1000); return () => clearInterval(id); }, []); // Our effect doesn't use any variables in the component scope return <h2>{count}</h2>; } (The identity of the setCount function is guaranteed to be stable so it's safe to omit.) Now, the setInterval callback executes once a second, but each time the inner call to setCount can use an up-to-date value for count (called c in the callback here.) In more complex cases (such as if one state depends on another state), try moving the state update logic outside the effect with the useReducer Hook. This article offers an example of how you can do this. The identity of the dispatch function from useReducer is always stable ¡ª even if the reducer function is declared inside the component and reads its props. As a last resort, if you want something like this in a class, you can use a ref to hold a mutable variable. Then you can write and read to it. For example: function Example(props) { // Keep latest props in a ref. const latestProps = useRef(props); useEffect(() => { latestProps.current = props; }); useEffect(() => { function tick() { // Read latest props at any time console.log(latestProps.current); } const id = setInterval(tick, 1000); return () => clearInterval(id); }, []); // This effect never re-runs} Only do this if you couldn't find a better alternative, as relying on mutation makes components less predictable. If there's a specific pattern that doesn't translate well, file an issue with a runnable example code and we can try to help.

How do I implement shouldComponentUpdate?

You can wrap a function component with React.memo to shallowly compare its props: const Button = React.memo((props) => { // your component }); It's not a Hook because it doesn't compose like Hooks do. React.memo is equivalent to PureComponent, but it only compares props. (You can also add a second argument to specify a custom comparison function that takes the old and new props. If it returns true, the update is skipped.) React.memo doesn't compare state because there is no single state object to compare. But you can make children pure too, or even optimize individual children with useMemo.

How to memoize calculations?

The useMemo Hook lets you cache calculations between multiple renders by ¡°remembering¡± the previous computation: const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); This code calls computeExpensiveValue(a, b). But if the dependencies [a, b] haven't changed since the last value, useMemo skips calling it a second time and simply reuses the last value it returned. Remember that the function passed to useMemo runs during rendering. Don't do anything there that you wouldn't normally do while rendering. For example, side effects belong in useEffect, not useMemo. You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to ¡°forget¡± some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo ¡ª and then add it to optimize performance. (For rare cases when a value must never be recomputed, you can lazily initialize a ref.) Conveniently, useMemo also lets you skip an expensive re-render of a child: function Parent({ a, b }) { // Only re-rendered if `a` changes: const child1 = useMemo(() => <Child1 a={a} />, [a]); // Only re-rendered if `b` changes: const child2 = useMemo(() => <Child2 b={b} />, [b]); return ( <> {child1} {child2} </> ) } Note that this approach won't work in a loop because Hook calls can't be placed inside loops. But you can extract a separate component for the list item, and call useMemo there.

How to create expensive objects lazily?

useMemo lets you memoize an expensive calculation if the dependencies are the same. However, it only serves as a hint, and doesn't guarantee the computation won't re-run. But sometimes you need to be sure an object is only created once. The first common use case is when creating the initial state is expensive: function Table(props) { // createRows() is called on every render const [rows, setRows] = useState(createRows(props.count)); // ... } To avoid re-creating the ignored initial state, we can pass a function to useState: function Table(props) { // createRows() is only called once const [rows, setRows] = useState(() => createRows(props.count)); // ... } React will only call this function during the first render. See the useState API reference. You might also occasionally want to avoid re-creating the useRef() initial value. For example, maybe you want to ensure some imperative class instance only gets created once: function Image(props) { // IntersectionObserver is created on every render const ref = useRef(new IntersectionObserver(onIntersect)); // ... } useRef does not accept a special function overload like useState. Instead, you can write your own function that creates and sets it lazily: function Image(props) { const ref = useRef(null); // IntersectionObserver is created lazily once function getObserver() { if (ref.current === null) { ref.current = new IntersectionObserver(onIntersect); } return ref.current; } // When you need it, call getObserver() // ... } This avoids creating an expensive object until it's truly needed for the first time. If you use Flow or TypeScript, you can also give getObserver() a non-nullable type for convenience.

Are Hooks slow because of creating functions in render?

No. In modern browsers, the raw performance of closures compared to classes doesn't differ significantly except in extreme scenarios. In addition, consider that the design of Hooks is more efficient in a couple ways:
  • Hooks avoid a lot of the overhead that classes require, like the cost of creating class instances and binding event handlers in the constructor.
  • Idiomatic code using Hooks doesn't need the deep component tree nesting that is prevalent in codebases that use higher-order components, render props, and context. With smaller component trees, React has less work to do.
Traditionally, performance concerns around inline functions in React have been related to how passing new callbacks on each render breaks shouldComponentUpdate optimizations in child components. Hooks approach this problem from three sides.
  • The useCallback Hook lets you keep the same callback reference between re-renders so that shouldComponentUpdate continues to work: // Will not change unless `a` or `b` changes const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]);
  • The useMemo Hook makes it easier to control when individual children update, reducing the need for pure components.
  • Finally, the useReducer Hook reduces the need to pass callbacks deeply, as explained below.

How to avoid passing callbacks down?

We've found that most people don't enjoy manually passing callbacks through every level of a component tree. Even though it is more explicit, it can feel like a lot of ¡°plumbing¡±. In large component trees, an alternative we recommend is to pass down a dispatch function from useReducer via context: const TodosDispatch = React.createContext(null); function TodosApp() { // Note: `dispatch` won't change between re-renders const [todos, dispatch] = useReducer(todosReducer); return ( <TodosDispatch.Provider value={dispatch}> <DeepTree todos={todos} /> </TodosDispatch.Provider> ); } Any child in the tree inside TodosApp can use the dispatch function to pass actions up to TodosApp: function DeepChild(props) { // If we want to perform an action, we can get dispatch from context. const dispatch = useContext(TodosDispatch); function handleClick() { dispatch({ type: 'add', text: 'hello' }); } return ( <button onClick={handleClick}>Add todo</button> ); } This is both more convenient from the maintenance perspective (no need to keep forwarding callbacks), and avoids the callback problem altogether. Passing dispatch down like this is the recommended pattern for deep updates. Note that you can still choose whether to pass the application state down as props (more explicit) or as context (more convenient for very deep updates). If you use context to pass down the state too, use two different context types ¡ª the dispatch context never changes, so components that read it don't need to rerender unless they also need the application state.

How to read an often-changing value from useCallback?

Note We recommend to pass dispatch down in context rather than individual callbacks in props. The approach below is only mentioned here for completeness and as an escape hatch. Also note that this pattern might cause problems in the concurrent mode. We plan to provide more ergonomic alternatives in the future, but the safest solution right now is to always invalidate the callback if some value it depends on changes.
In some rare cases you might need to memoize a callback with useCallback but the memoization doesn't work very well because the inner function has to be re-created too often. If the function you're memoizing is an event handler and isn't used during rendering, you can use ref as an instance variable, and save the last committed value into it manually: function Form() { const [text, updateText] = useState(''); const textRef = useRef(); useEffect(() => { textRef.current = text; // Write it to the ref }); const handleSubmit = useCallback(() => { const currentText = textRef.current; // Read it from the ref alert(currentText); }, [textRef]); // Don't recreate handleSubmit like [text] would do return ( <> <input value={text} onChange={e => updateText(e.target.value)} /> <ExpensiveTree onSubmit={handleSubmit} /> </> ); } This is a rather convoluted pattern but it shows that you can do this escape hatch optimization if you need it. It's more bearable if you extract it to a custom Hook: function Form() { const [text, updateText] = useState(''); // Will be memoized even if `text` changes: const handleSubmit = useEventCallback(() => { alert(text); }, [text]); return ( <> <input value={text} onChange={e => updateText(e.target.value)} /> <ExpensiveTree onSubmit={handleSubmit} /> </> ); } function useEventCallback(fn, dependencies) { const ref = useRef(() => { throw new Error('Cannot call an event handler while rendering.'); }); useEffect(() => { ref.current = fn; }, [fn, ...dependencies]); return useCallback(() => { const fn = ref.current; return fn(); }, [ref]); } In either case, we don't recommend this pattern and only show it here for completeness. Instead, it is preferable to avoid passing callbacks deep down.

Under the Hood

How does React associate Hook calls with components?

React keeps track of the currently rendering component. Thanks to the Rules of Hooks, we know that Hooks are only called from React components (or custom Hooks ¡ª which are also only called from React components). There is an internal list of ¡°memory cells¡± associated with each component. They're just JavaScript objects where we can put some data. When you call a Hook like useState(), it reads the current cell (or initializes it during the first render), and then moves the pointer to the next one. This is how multiple useState() calls each get independent local state.

What is the prior art for Hooks?

Hooks synthesize ideas from several different sources:
  • Our old experiments with functional APIs in the react-future repository.
  • React community's experiments with render prop APIs, including Ryan Florence's Reactions Component.
  • Dominic Gannaway's adopt keyword proposal as a sugar syntax for render props.
  • State variables and state cells in DisplayScript.
  • Reducer components in ReasonReact.
  • Subscriptions in Rx.
  • Algebraic effects in Multicore OCaml.
Sebastian Markb ge came up with the original design for Hooks, later refined by Andrew Clark, Sophie Alpert, Dominic Gannaway, and other members of the React team.

Testing Overview

You can test React components similar to testing other JavaScript code. There are a few ways to test React components. Broadly, they divide into two categories:
  • Rendering component trees in a simplified test environment and asserting on their output.
  • Running a complete app in a realistic browser environment (also known as ¡°end-to-end¡± tests).
This documentation section focuses on testing strategies for the first case. While full end-to-end tests can be very useful to prevent regressions to important workflows, such tests are not concerned with React components in particular, and are out of the scope of this section.

Tradeoffs

When choosing testing tools, it is worth considering a few tradeoffs:
  • Iteration speed vs Realistic environment: Some tools offer a very quick feedback loop between making a change and seeing the result, but don't model the browser behavior precisely. Other tools might use a real browser environment, but reduce the iteration speed and are flakier on a continuous integration server.
  • How much to mock: With components, the distinction between a ¡°unit¡± and ¡°integration¡± test can be blurry. If you're testing a form, should its test also test the buttons inside of it? Or should a button component have its own test suite? Should refactoring a button ever break the form test?
Different answers may work for different teams and products.

Recommended Tools

Jest is a JavaScript test runner that lets you access the DOM via jsdom. While jsdom is only an approximation of how the browser works, it is often good enough for testing React components. Jest provides a great iteration speed combined with powerful features like mocking modules and timers so you can have more control over how the code executes. React Testing Library is a set of helpers that let you test React components without relying on their implementation details. This approach makes refactoring a breeze and also nudges you towards best practices for accessibility. Although it doesn't provide a way to ¡°shallowly¡± render a component without its children, a test runner like Jest lets you do this by mocking.

Learn More

This section is divided in two pages:
  • Recipes: Common patterns when writing tests for React components.
  • Environments: What to consider when setting up a testing environment for React components.

Testing Recipes

Common testing patterns for React components.
Note: This page assumes you're using Jest as a test runner. If you use a different test runner, you may need to adjust the API, but the overall shape of the solution will likely be the same. Read more details on setting up a testing environment on the Testing Environments page.
On this page, we will primarily use function components. However, these testing strategies don't depend on implementation details, and work just as well for class components too.
  • Setup/Teardown
  • act()
  • Rendering
  • Data Fetching
  • Mocking Modules
  • Events
  • Timers
  • Snapshot Testing
  • Multiple Renderers
  • Something Missing?

Setup/Teardown

For each test, we usually want to render our React tree to a DOM element that's attached to document. This is important so that it can receive DOM events. When the test ends, we want to ¡°clean up¡± and unmount the tree from the document. A common way to do it is to use a pair of beforeEach and afterEach blocks so that they'll always run and isolate the effects of a test to itself: import { unmountComponentAtNode } from "react-dom"; let container = null; beforeEach(() => { // setup a DOM element as a render target container = document.createElement("div"); document.body.appendChild(container); }); afterEach(() => { // cleanup on exiting unmountComponentAtNode(container); container.remove(); container = null; }); You may use a different pattern, but keep in mind that we want to execute the cleanup even if a test fails. Otherwise, tests can become ¡°leaky¡±, and one test can change the behavior of another test. That makes them difficult to debug.

act()

When writing UI tests, tasks like rendering, user events, or data fetching can be considered as ¡°units¡± of interaction with a user interface. react-dom/test-utils provides a helper called act() that makes sure all updates related to these ¡°units¡± have been processed and applied to the DOM before you make any assertions: act(() => { // render components }); // make assertions This helps make your tests run closer to what real users would experience when using your application. The rest of these examples use act() to make these guarantees. You might find using act() directly a bit too verbose. To avoid some of the boilerplate, you could use a library like React Testing Library, whose helpers are wrapped with act().
Note: The name act comes from the Arrange-Act-Assert pattern.

Rendering

Commonly, you might want to test whether a component renders correctly for given props. Consider a simple component that renders a message based on a prop: // hello.js import React from "react"; export default function Hello(props) { if (props.name) { return <h2>Hello, {props.name}!</h2>; } else { return <span>Hey, stranger</span>; } } We can write a test for this component: // hello.test.js import React from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { act } from "react-dom/test-utils"; import Hello from "./hello"; let container = null; beforeEach(() => { // setup a DOM element as a render target container = document.createElement("div"); document.body.appendChild(container); }); afterEach(() => { // cleanup on exiting unmountComponentAtNode(container); container.remove(); container = null; }); it("renders with or without a name", () => { act(() => { render(<Hello />, container); }); expect(container.textContent).toBe("Hey, stranger"); act(() => { render(<Hello name="Jenny" />, container); }); expect(container.textContent).toBe("Hello, Jenny!"); act(() => { render(<Hello name="Margaret" />, container); }); expect(container.textContent).toBe("Hello, Margaret!"); });

Data Fetching

Instead of calling real APIs in all your tests, you can mock requests with dummy data. Mocking data fetching with ¡°fake¡± data prevents flaky tests due to an unavailable backend, and makes them run faster. Note: you may still want to run a subset of tests using an ¡°end-to-end¡± framework that tells whether the whole app is working together. // user.js import React, { useState, useEffect } from "react"; export default function User(props) { const [user, setUser] = useState(null); async function fetchUserData(id) { const response = await fetch("/" + id); setUser(await response.json()); } useEffect(() => { fetchUserData(props.id); }, [props.id]); if (!user) { return "loading..."; } return ( <details> <summary>{user.name}</summary> <strong>{user.age}</strong> years old <br /> lives in {user.address} </details> ); } We can write tests for it: // user.test.js import React from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { act } from "react-dom/test-utils"; import User from "./user"; let container = null; beforeEach(() => { // setup a DOM element as a render target container = document.createElement("div"); document.body.appendChild(container); }); afterEach(() => { // cleanup on exiting unmountComponentAtNode(container); container.remove(); container = null; }); it("renders user data", async () => { const fakeUser = { name: "Joni Baez", age: "32", address: "123, Charming Avenue" }; jest.spyOn(global, "fetch").mockImplementation(() => Promise.resolve({ json: () => Promise.resolve(fakeUser) }) ); // Use the asynchronous version of act to apply resolved promises await act(async () => { render(<User id="123" />, container); }); expect(container.querySelector("summary").textContent).toBe(fakeUser.name); expect(container.querySelector("strong").textContent).toBe(fakeUser.age); expect(container.textContent).toContain(fakeUser.address); // remove the mock to ensure tests are completely isolated global.fetch.mockRestore();});

Mocking Modules

Some modules might not work well inside a testing environment, or may not be as essential to the test itself. Mocking out these modules with dummy replacements can make it easier to write tests for your own code. Consider a Contact component that embeds a third-party GoogleMap component: // map.js import React from "react"; import { LoadScript, GoogleMap } from "react-google-maps"; export default function Map(props) { return ( <LoadScript id="script-loader" googleMapsApiKey="YOUR_API_KEY"> <GoogleMap id="example-map" center={props.center} /> </LoadScript> ); } // contact.js import React from "react"; import Map from "./map"; export default function Contact(props) { return ( <div> <address> Contact {props.name} via{" "} <a data-testid="email" href={"mailto:" + props.email}> email </a> or on their <a data-testid="site" href={props.site}> website </a>. </address> <Map center={props.center} /> </div> ); } If we don't want to load this component in our tests, we can mock out the dependency itself to a dummy component, and run our tests: // contact.test.js import React from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { act } from "react-dom/test-utils"; import Contact from "./contact"; import MockedMap from "./map"; jest.mock("./map", () => { return function DummyMap(props) { return ( <div data-testid="map"> {props.center.lat}:{props.center.long} </div> ); };}); let container = null; beforeEach(() => { // setup a DOM element as a render target container = document.createElement("div"); document.body.appendChild(container); }); afterEach(() => { // cleanup on exiting unmountComponentAtNode(container); container.remove(); container = null; }); it("should render contact information", () => { const center = { lat: 0, long: 0 }; act(() => { render( <Contact name="Joni Baez" email="test@example.com" site="http://test.com" center={center} />, container ); }); expect( container.querySelector("[data-testid='email']").getAttribute("href") ).toEqual("mailto:test@example.com"); expect( container.querySelector('[data-testid="site"]').getAttribute("href") ).toEqual("http://test.com"); expect(container.querySelector('[data-testid="map"]').textContent).toEqual( "0:0" ); });

Events

We recommend dispatching real DOM events on DOM elements, and then asserting on the result. Consider a Toggle component: // toggle.js import React, { useState } from "react"; export default function Toggle(props) { const [state, setState] = useState(false); return ( <button onClick={() => { setState(previousState => !previousState); props.onChange(!state); }} data-testid="toggle" > {state === true ? "Turn off" : "Turn on"} </button> ); } We could write tests for it: // toggle.test.js import React from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { act } from "react-dom/test-utils"; import Toggle from "./toggle"; let container = null; beforeEach(() => { // setup a DOM element as a render target container = document.createElement("div"); document.body.appendChild(container);}); afterEach(() => { // cleanup on exiting unmountComponentAtNode(container); container.remove(); container = null; }); it("changes value when clicked", () => { const onChange = jest.fn(); act(() => { render(<Toggle onChange={onChange} />, container); }); // get ahold of the button element, and trigger some clicks on it const button = document.querySelector("[data-testid=toggle]"); expect(button.innerHTML).toBe("Turn on"); act(() => { button.dispatchEvent(new MouseEvent("click", { bubbles: true })); }); expect(onChange).toHaveBeenCalledTimes(1); expect(button.innerHTML).toBe("Turn off"); act(() => { for (let i = 0; i < 5; i++) { button.dispatchEvent(new MouseEvent("click", { bubbles: true })); } }); expect(onChange).toHaveBeenCalledTimes(6); expect(button.innerHTML).toBe("Turn on"); }); Different DOM events and their properties are described in MDN. Note that you need to pass { bubbles: true } in each event you create for it to reach the React listener because React automatically delegates events to the root.
Note: React Testing Library offers a more concise helper for firing events.

Timers

Your code might use timer-based functions like setTimeout to schedule more work in the future. In this example, a multiple choice panel waits for a selection and advances, timing out if a selection isn't made in 5 seconds: // card.js import React, { useEffect } from "react"; export default function Card(props) { useEffect(() => { const timeoutID = setTimeout(() => { props.onSelect(null); }, 5000); return () => { clearTimeout(timeoutID); }; }, [props.onSelect]); return [1, 2, 3, 4].map(choice => ( <button key={choice} data-testid={choice} onClick={() => props.onSelect(choice)} > {choice} </button> )); } We can write tests for this component by leveraging Jest's timer mocks, and testing the different states it can be in. // card.test.js import React from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { act } from "react-dom/test-utils"; import Card from "./card"; jest.useFakeTimers(); let container = null; beforeEach(() => { // setup a DOM element as a render target container = document.createElement("div"); document.body.appendChild(container); }); afterEach(() => { // cleanup on exiting unmountComponentAtNode(container); container.remove(); container = null; }); it("should select null after timing out", () => { const onSelect = jest.fn(); act(() => { render(<Card onSelect={onSelect} />, container); }); // move ahead in time by 100ms act(() => { jest.advanceTimersByTime(100); }); expect(onSelect).not.toHaveBeenCalled(); // and then move ahead by 5 seconds act(() => { jest.advanceTimersByTime(5000); }); expect(onSelect).toHaveBeenCalledWith(null); }); it("should cleanup on being removed", () => { const onSelect = jest.fn(); act(() => { render(<Card onSelect={onSelect} />, container); }); act(() => { jest.advanceTimersByTime(100); }); expect(onSelect).not.toHaveBeenCalled(); // unmount the app act(() => { render(null, container); }); act(() => { jest.advanceTimersByTime(5000); }); expect(onSelect).not.toHaveBeenCalled(); }); it("should accept selections", () => { const onSelect = jest.fn(); act(() => { render(<Card onSelect={onSelect} />, container); }); act(() => { container .querySelector("[data-testid='2']") .dispatchEvent(new MouseEvent("click", { bubbles: true })); }); expect(onSelect).toHaveBeenCalledWith(2); }); You can use fake timers only in some tests. Above, we enabled them by calling jest.useFakeTimers(). The main advantage they provide is that your test doesn't actually have to wait five seconds to execute, and you also didn't need to make the component code more convoluted just for testing.

Snapshot Testing

Frameworks like Jest also let you save ¡°snapshots¡± of data with toMatchSnapshot / toMatchInlineSnapshot. With these, we can ¡°save¡± the rendered component output and ensure that a change to it has to be explicitly committed as a change to the snapshot. In this example, we render a component and format the rendered HTML with the pretty package, before saving it as an inline snapshot: // hello.test.js, again import React from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { act } from "react-dom/test-utils"; import pretty from "pretty"; import Hello from "./hello"; let container = null; beforeEach(() => { // setup a DOM element as a render target container = document.createElement("div"); document.body.appendChild(container); }); afterEach(() => { // cleanup on exiting unmountComponentAtNode(container); container.remove(); container = null; }); it("should render a greeting", () => { act(() => { render(<Hello />, container); }); expect( pretty(container.innerHTML) ).toMatchInlineSnapshot(); /* ... gets filled automatically by jest ... */ act(() => { render(<Hello name="Jenny" />, container); }); expect( pretty(container.innerHTML) ).toMatchInlineSnapshot(); /* ... gets filled automatically by jest ... */ act(() => { render(<Hello name="Margaret" />, container); }); expect( pretty(container.innerHTML) ).toMatchInlineSnapshot(); /* ... gets filled automatically by jest ... */ }); It's typically better to make more specific assertions than to use snapshots. These kinds of tests include implementation details so they break easily, and teams can get desensitized to snapshot breakages. Selectively mocking some child components can help reduce the size of snapshots and keep them readable for the code review.

Multiple Renderers

In rare cases, you may be running a test on a component that uses multiple renderers. For example, you may be running snapshot tests on a component with react-test-renderer, that internally uses ReactDOM.render inside a child component to render some content. In this scenario, you can wrap updates with act()s corresponding to their renderers. import { act as domAct } from "react-dom/test-utils"; import { act as testAct, create } from "react-test-renderer"; // ... let root; domAct(() => { testAct(() => { root = create(<App />); }); }); expect(root).toMatchSnapshot();

Something Missing?

If some common scenario is not covered, please let us know on the issue tracker for the documentation website.

Testing Environments

This document goes through the factors that can affect your environment and recommendations for some scenarios.

Test runners

Test runners like Jest, mocha, ava let you write test suites as regular JavaScript, and run them as part of your development process. Additionally, test suites are run as part of continuous integration.
  • Jest is widely compatible with React projects, supporting features like mocked modules and timers, and jsdom support. If you use Create React App, Jest is already included out of the box with useful defaults.
  • Libraries like mocha work well in real browser environments, and could help for tests that explicitly need it.
  • End-to-end tests are used for testing longer flows across multiple pages, and require a different setup.

Mocking a rendering surface

Tests often run in an environment without access to a real rendering surface like a browser. For these environments, we recommend simulating a browser with jsdom, a lightweight browser implementation that runs inside Node.js. In most cases, jsdom behaves like a regular browser would, but doesn't have features like layout and navigation. This is still useful for most web-based component tests, since it runs quicker than having to start up a browser for each test. It also runs in the same process as your tests, so you can write code to examine and assert on the rendered DOM. Just like in a real browser, jsdom lets us model user interactions; tests can dispatch events on DOM nodes, and then observe and assert on the side effects of these actions (example). A large portion of UI tests can be written with the above setup: using Jest as a test runner, rendered to jsdom, with user interactions specified as sequences of browser events, powered by the act() helper (example). For example, a lot of React's own tests are written with this combination. If you're writing a library that tests mostly browser-specific behavior, and requires native browser behavior like layout or real inputs, you could use a framework like mocha. In an environment where you can't simulate a DOM (e.g. testing React Native components on Node.js), you could use event simulation helpers to simulate interactions with elements. Alternately, you could use the fireEvent helper from @testing-library/react-native. Frameworks like Cypress, puppeteer and webdriver are useful for running end-to-end tests.

Mocking functions

When writing tests, we'd like to mock out the parts of our code that don't have equivalents inside our testing environment (e.g. checking navigator.onLine status inside Node.js). Tests could also spy on some functions, and observe how other parts of the test interact with them. It is then useful to be able to selectively mock these functions with test-friendly versions. This is especially useful for data fetching. It is usually preferable to use ¡°fake¡± data for tests to avoid the slowness and flakiness due to fetching from real API endpoints (example). This helps make the tests predictable. Libraries like Jest and sinon, among others, support mocked functions. For end-to-end tests, mocking network can be more difficult, but you might also want to test the real API endpoints in them anyway.

Mocking modules

Some components have dependencies for modules that may not work well in test environments, or aren't essential to our tests. It can be useful to selectively mock these modules out with suitable replacements (example). On Node.js, runners like Jest support mocking modules. You could also use libraries like mock-require.

Mocking timers

Components might be using time-based functions like setTimeout, setInterval, or Date.now. In testing environments, it can be helpful to mock these functions out with replacements that let you manually ¡°advance¡± time. This is great for making sure your tests run fast! Tests that are dependent on timers would still resolve in order, but quicker (example). Most frameworks, including Jest, sinon and lolex, let you mock timers in your tests. Sometimes, you may not want to mock timers. For example, maybe you're testing an animation, or interacting with an endpoint that's sensitive to timing (like an API rate limiter). Libraries with timer mocks let you enable and disable them on a per test/suite basis, so you can explicitly choose how these tests would run.

End-to-end tests

End-to-end tests are useful for testing longer workflows, especially when they're critical to your business (such as payments or signups). For these tests, you'd probably want to test how a real browser renders the whole app, fetches data from the real API endpoints, uses sessions and cookies, navigates between different links. You might also likely want to make assertions not just on the DOM state, but on the backing data as well (e.g. to verify whether the updates have been persisted to the database). In this scenario, you would use a framework like Cypress or a library like puppeteer so you can navigate between multiple routes and assert on side effects not just in the browser, but potentially on the backend as well.

Introducing Concurrent Mode (Experimental)

Caution: This page describes experimental features that are not yet available in a stable release. Don't rely on experimental builds of React in production apps. These features may change significantly and without a warning before they become a part of React. This documentation is aimed at early adopters and people who are curious. If you're new to React, don't worry about these features ¡ª you don't need to learn them right now.
This page provides a theoretical overview of Concurrent Mode. For a more practical introduction, you might want to check out the next sections:
  • Suspense for Data Fetching describes a new mechanism for fetching data in React components.
  • Concurrent UI Patterns shows some UI patterns made possible by Concurrent Mode and Suspense.
  • Adopting Concurrent Mode explains how you can try Concurrent Mode in your project.
  • Concurrent Mode API Reference documents the new APIs available in experimental builds.

What Is Concurrent Mode?

Concurrent Mode is a set of new features that help React apps stay responsive and gracefully adjust to the user's device capabilities and network speed. These features are still experimental and are subject to change. They are not yet a part of a stable React release, but you can try them in an experimental build.

Blocking vs Interruptible Rendering

To explain Concurrent Mode, we'll use version control as a metaphor. If you work on a team, you probably use a version control system like Git and work on branches. When a branch is ready, you can merge your work into master so that other people can pull it. Before version control existed, the development workflow was very different. There was no concept of branches. If you wanted to edit some files, you had to tell everyone not to touch those files until you've finished your work. You couldn't even start working on them concurrently with that person ¡ª you were literally blocked by them. This illustrates how UI libraries, including React, typically work today. Once they start rendering an update, including creating new DOM nodes and running the code inside components, they can't interrupt this work. We'll call this approach ¡°blocking rendering¡±. In Concurrent Mode, rendering is not blocking. It is interruptible. This improves the user experience. It also unlocks new features that weren't possible before. Before we look at concrete examples in the next chapters, we'll do a high-level overview of new features.

Interruptible Rendering

Consider a filterable product list. Have you ever typed into a list filter and felt that it stutters on every key press? Some of the work to update the product list might be unavoidable, such as creating new DOM nodes or the browser performing layout. However, when and how we perform that work plays a big role. A common way to work around the stutter is to ¡°debounce¡± the input. When debouncing, we only update the list after the user stops typing. However, it can be frustrating that the UI doesn't update while we're typing. As an alternative, we could ¡°throttle¡± the input, and update the list with a certain maximum frequency. But then on lower-powered devices we'd still end up with stutter. Both debouncing and throttling create a suboptimal user experience. The reason for the stutter is simple: once rendering begins, it can't be interrupted. So the browser can't update the text input right after the key press. No matter how good a UI library (such as React) might look on a benchmark, if it uses blocking rendering, a certain amount of work in your components will always cause stutter. And, often, there is no easy fix. Concurrent Mode fixes this fundamental limitation by making rendering interruptible. This means when the user presses another key, React doesn't need to block the browser from updating the text input. Instead, it can let the browser paint an update to the input, and then continue rendering the updated list in memory. When the rendering is finished, React updates the DOM, and changes are reflected on the screen. Conceptually, you can think of this as React preparing every update ¡°on a branch¡±. Just like you can abandon work in branches or switch between them, React in Concurrent Mode can interrupt an ongoing update to do something more important, and then come back to what it was doing earlier. This technique might also remind you of double buffering in video games. Concurrent Mode techniques reduce the need for debouncing and throttling in UI. Because rendering is interruptible, React doesn't need to artificially delay work to avoid stutter. It can start rendering right away, but interrupt this work when needed to keep the app responsive.

Intentional Loading Sequences

We've said before that Concurrent Mode is like React working ¡°on a branch¡±. Branches are useful not only for short-term fixes, but also for long-running features. Sometimes you might work on a feature, but it could take weeks before it's in a ¡°good enough state¡± to merge into master. This side of our version control metaphor applies to rendering too. Imagine we're navigating between two screens in an app. Sometimes, we might not have enough code and data loaded to show a ¡°good enough¡± loading state to the user on the new screen. Transitioning to an empty screen or a large spinner can be a jarring experience. However, it's also common that the necessary code and data doesn't take too long to fetch. Wouldn't it be nicer if React could stay on the old screen for a little longer, and ¡°skip¡± the ¡°bad loading state¡± before showing the new screen? While this is possible today, it can be difficult to orchestrate. In Concurrent Mode, this feature is built-in. React starts preparing the new screen in memory first ¡ª or, as our metaphor goes, ¡°on a different branch¡±. So React can wait before updating the DOM so that more content can load. In Concurrent Mode, we can tell React to keep showing the old screen, fully interactive, with an inline loading indicator. And when the new screen is ready, React can take us to it.

Concurrency

Let's recap the two examples above and see how Concurrent Mode unifies them. In Concurrent Mode, React can work on several state updates concurrently ¡ª just like branches let different team members work independently:
  • For CPU-bound updates (such as creating DOM nodes and running component code), concurrency means that a more urgent update can ¡°interrupt¡± rendering that has already started.
  • For IO-bound updates (such as fetching code or data from the network), concurrency means that React can start rendering in memory even before all the data arrives, and skip showing jarring empty loading states.
Importantly, the way you use React is the same. Concepts like components, props, and state fundamentally work the same way. When you want to update the screen, you set the state. React uses a heuristic to decide how ¡°urgent¡± an update is, and lets you adjust it with a few lines of code so that you can achieve the desired user experience for every interaction.

Putting Research into Production

There is a common theme around Concurrent Mode features. Its mission is to help integrate the findings from the Human-Computer Interaction research into real UIs. For example, research shows that displaying too many intermediate loading states when transitioning between screens makes a transition feel slower. This is why Concurrent Mode shows new loading states on a fixed ¡°schedule¡± to avoid jarring and too frequent updates. Similarly, we know from research that interactions like hover and text input need to be handled within a very short period of time, while clicks and page transitions can wait a little longer without feeling laggy. The different ¡°priorities¡± that Concurrent Mode uses internally roughly correspond to the interaction categories in the human perception research. Teams with a strong focus on user experience sometimes solve similar problems with one-off solutions. However, those solutions rarely survive for a long time, as they're hard to maintain. With Concurrent Mode, our goal is to bake the UI research findings into the abstraction itself, and provide idiomatic ways to use them. As a UI library, React is well-positioned to do that.

Next Steps

Now you know what Concurrent Mode is all about! On the next pages, you'll learn more details about specific topics:
  • Suspense for Data Fetching describes a new mechanism for fetching data in React components.
  • Concurrent UI Patterns shows some UI patterns made possible by Concurrent Mode and Suspense.
  • Adopting Concurrent Mode explains how you can try Concurrent Mode in your project.
  • Concurrent Mode API Reference documents the new APIs available in experimental builds.

Suspense for Data Fetching (Experimental)

Caution: This page describes experimental features that are not yet available in a stable release. Don't rely on experimental builds of React in production apps. These features may change significantly and without a warning before they become a part of React. This documentation is aimed at early adopters and people who are curious. If you're new to React, don't worry about these features ¡ª you don't need to learn them right now. For example, if you're looking for a data fetching tutorial that works today, read this article instead.
React 16.6 added a <Suspense> component that lets you ¡°wait¡± for some code to load and declaratively specify a loading state (like a spinner) while we're waiting: const ProfilePage = React.lazy(() => import('./ProfilePage')); // Lazy-loaded // Show a spinner while the profile is loading <Suspense fallback={<Spinner />}> <ProfilePage /> </Suspense> Suspense for Data Fetching is a new feature that lets you also use <Suspense> to declaratively ¡°wait¡± for anything else, including data. This page focuses on the data fetching use case, but it can also wait for images, scripts, or other asynchronous work.
  • What Is Suspense, Exactly?
    • What Suspense Is Not
    • What Suspense Lets You Do
  • Using Suspense in Practice
    • What If I Don't Use Relay?
    • For Library Authors
  • Traditional Approaches vs Suspense
    • Approach 1: Fetch-on-Render (not using Suspense)
    • Approach 2: Fetch-Then-Render (not using Suspense)
    • Approach 3: Render-as-You-Fetch (using Suspense)
  • Start Fetching Early
    • We're Still Figuring This Out
  • Suspense and Race Conditions
    • Race Conditions with useEffect
    • Race Conditions with componentDidUpdate
    • The Problem
    • Solving Race Conditions with Suspense
  • Handling Errors
  • Next Steps

What Is Suspense, Exactly?

Suspense lets your components ¡°wait¡± for something before they can render. In this example, two components wait for an asynchronous API call to fetch some data: const resource = fetchProfileData(); function ProfilePage() { return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails /> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline /> </Suspense> </Suspense> ); } function ProfileDetails() { // Try to read user info, although it might not have loaded yet const user = resource.user.read(); return <h2>{user.name}</h2>; } function ProfileTimeline() { // Try to read posts, although they might not have loaded yet const posts = resource.posts.read(); return ( <ul> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } Try it on CodeSandbox This demo is a teaser. Don't worry if it doesn't quite make sense yet. We'll talk more about how it works below. Keep in mind that Suspense is more of a mechanism, and particular APIs like fetchProfileData() or resource.posts.read() in the above example are not very important. If you're curious, you can find their definitions right in the demo sandbox. Suspense is not a data fetching library. It's a mechanism for data fetching libraries to communicate to React that the data a component is reading is not ready yet. React can then wait for it to be ready and update the UI. At Facebook, we use Relay and its new Suspense integration. We expect that other libraries like Apollo can provide similar integrations. In the long term, we intend Suspense to become the primary way to read asynchronous data from components ¡ª no matter where that data is coming from.

What Suspense Is Not

Suspense is significantly different from existing approaches to these problems, so reading about it for the first time often leads to misconceptions. Let's clarify the most common ones:
  • It is not a data fetching implementation. It does not assume that you use GraphQL, REST, or any other particular data format, library, transport, or protocol.
  • It is not a ready-to-use client. You can't ¡°replace¡± fetch or Relay with Suspense. But you can use a library that's integrated with Suspense (for example, new Relay APIs).
  • It does not couple data fetching to the view layer. It helps orchestrate displaying the loading states in your UI, but it doesn't tie your network logic to React components.

What Suspense Lets You Do

So what's the point of Suspense? There are a few ways we can answer this:
  • It lets data fetching libraries deeply integrate with React. If a data fetching library implements Suspense support, using it from React components feels very natural.
  • It lets you orchestrate intentionally designed loading states. It doesn't say how the data is fetched, but it lets you closely control the visual loading sequence of your app.
  • It helps you avoid race conditions. Even with await, asynchronous code is often error-prone. Suspense feels more like reading data synchronously ¡ª as if it were already loaded.

Using Suspense in Practice

At Facebook, so far we have only used the Relay integration with Suspense in production. If you're looking for a practical guide to get started today, check out the Relay Guide! It demonstrates patterns that have already worked well for us in production. The code demos on this page use a ¡°fake¡± API implementation rather than Relay. This makes them easier to understand if you're not familiar with GraphQL, but they won't tell you the ¡°right way¡± to build an app with Suspense. This page is more conceptual and is intended to help you see why Suspense works in a certain way, and which problems it solves.

What If I Don't Use Relay?

If you don't use Relay today, you might have to wait before you can really try Suspense in your app. So far, it's the only implementation that we tested in production and are confident in. Over the next several months, many libraries will appear with different takes on Suspense APIs. If you prefer to learn when things are more stable, you might prefer to ignore this work for now, and come back when the Suspense ecosystem is more mature. You can also write your own integration for a data fetching library, if you'd like.

For Library Authors

We expect to see a lot of experimentation in the community with other libraries. There is one important thing to note for data fetching library authors. Although it's technically doable, Suspense is not currently intended as a way to start fetching data when a component renders. Rather, it lets components express that they're ¡°waiting¡± for data that is already being fetched. Building Great User Experiences with Concurrent Mode and Suspense describes why this matters and how to implement this pattern in practice. Unless you have a solution that helps prevent waterfalls, we suggest to prefer APIs that favor or enforce fetching before render. For a concrete example, you can look at how Relay Suspense API enforces preloading. Our messaging about this hasn't been very consistent in the past. Suspense for Data Fetching is still experimental, so you can expect our recommendations to change over time as we learn more from production usage and understand the problem space better.

Traditional Approaches vs Suspense

We could introduce Suspense without mentioning the popular data fetching approaches. However, this makes it more difficult to see which problems Suspense solves, why these problems are worth solving, and how Suspense is different from the existing solutions. Instead, we'll look at Suspense as a logical next step in a sequence of approaches:
  • Fetch-on-render (for example, fetch in useEffect): Start rendering components. Each of these components may trigger data fetching in their effects and lifecycle methods. This approach often leads to ¡°waterfalls¡±.
  • Fetch-then-render (for example, Relay without Suspense): Start fetching all the data for the next screen as early as possible. When the data is ready, render the new screen. We can't do anything until the data arrives.
  • Render-as-you-fetch (for example, Relay with Suspense): Start fetching all the required data for the next screen as early as possible, and start rendering the new screen immediately ¡ª before we get a network response. As data streams in, React retries rendering components that still need data until they're all ready.
Note This is a bit simplified, and in practice solutions tend to use a mix of different approaches. Still, we will look at them in isolation to better contrast their tradeoffs.
To compare these approaches, we'll implement a profile page with each of them.

Approach 1: Fetch-on-Render (not using Suspense)

A common way to fetch data in React apps today is to use an effect: // In a function component: useEffect(() => { fetchSomething(); }, []); // Or, in a class component: componentDidMount() { fetchSomething(); } We call this approach ¡°fetch-on-render¡± because it doesn't start fetching until after the component has rendered on the screen. This leads to a problem known as a ¡°waterfall¡±. Consider these <ProfilePage> and <ProfileTimeline> components: function ProfilePage() { const [user, setUser] = useState(null); useEffect(() => { fetchUser().then(u => setUser(u)); }, []); if (user === null) { return <p>Loading profile...</p>; } return ( <> <h2>{user.name}</h2> <ProfileTimeline /> </> ); } function ProfileTimeline() { const [posts, setPosts] = useState(null); useEffect(() => { fetchPosts().then(p => setPosts(p)); }, []); if (posts === null) { return <h3>Loading posts...</h3>; } return ( <ul> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } Try it on CodeSandbox If you run this code and watch the console logs, you'll notice the sequence is:
  1. We start fetching user details
  2. We wait¡­
  3. We finish fetching user details
  4. We start fetching posts
  5. We wait¡­
  6. We finish fetching posts
If fetching user details takes three seconds, we'll only start fetching the posts after three seconds! That's a ¡°waterfall¡±: an unintentional sequence that should have been parallelized. Waterfalls are common in code that fetches data on render. They're possible to solve, but as the product grows, many people prefer to use a solution that guards against this problem.

Approach 2: Fetch-Then-Render (not using Suspense)

Libraries can prevent waterfalls by offering a more centralized way to do data fetching. For example, Relay solves this problem by moving the information about the data a component needs to statically analyzable fragments, which later get composed into a single query. On this page, we don't assume knowledge of Relay, so we won't be using it for this example. Instead, we'll write something similar manually by combining our data fetching methods: function fetchProfileData() { return Promise.all([ fetchUser(), fetchPosts() ]).then(([user, posts]) => { return {user, posts}; }) } In this example, <ProfilePage> waits for both requests but starts them in parallel: // Kick off fetching as early as possibleconst promise = fetchProfileData(); function ProfilePage() { const [user, setUser] = useState(null); const [posts, setPosts] = useState(null); useEffect(() => { promise.then(data => { setUser(data.user); setPosts(data.posts); }); }, []); if (user === null) { return <p>Loading profile...</p>; } return ( <> <h2>{user.name}</h2> <ProfileTimeline posts={posts} /> </> ); } // The child doesn't trigger fetching anymore function ProfileTimeline({ posts }) { if (posts === null) { return <h3>Loading posts...</h3>; } return ( <ul> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } Try it on CodeSandbox The event sequence now becomes like this:
  1. We start fetching user details
  2. We start fetching posts
  3. We wait¡­
  4. We finish fetching user details
  5. We finish fetching posts
We've solved the previous network ¡°waterfall¡±, but accidentally introduced a different one. We wait for all data to come back with Promise.all() inside fetchProfileData, so now we can't render profile details until the posts have been fetched too. We have to wait for both. Of course, this is possible to fix in this particular example. We could remove the Promise.all() call, and wait for both Promises separately. However, this approach gets progressively more difficult as the complexity of our data and component tree grows. It's hard to write reliable components when arbitrary parts of the data tree may be missing or stale. So fetching all data for the new screen and then rendering is often a more practical option.

Approach 3: Render-as-You-Fetch (using Suspense)

In the previous approach, we fetched data before we called setState:
  1. Start fetching
  2. Finish fetching
  3. Start rendering
With Suspense, we still start fetching first, but we flip the last two steps around:
  1. Start fetching
  2. Start rendering
  3. Finish fetching
With Suspense, we don't wait for the response to come back before we start rendering. In fact, we start rendering pretty much immediately after kicking off the network request: // This is not a Promise. It's a special object from our Suspense integration. const resource = fetchProfileData(); function ProfilePage() { return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails /> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline /> </Suspense> </Suspense> ); } function ProfileDetails() { // Try to read user info, although it might not have loaded yet const user = resource.user.read(); return <h2>{user.name}</h2>; } function ProfileTimeline() { // Try to read posts, although they might not have loaded yet const posts = resource.posts.read(); return ( <ul> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } Try it on CodeSandbox Here's what happens when we render <ProfilePage> on the screen:
  1. We've already kicked off the requests in fetchProfileData(). It gave us a special ¡°resource¡± instead of a Promise. In a realistic example, it would be provided by our data library's Suspense integration, like Relay.
  2. React tries to render <ProfilePage>. It returns <ProfileDetails> and <ProfileTimeline> as children.
  3. React tries to render <ProfileDetails>. It calls resource.user.read(). None of the data is fetched yet, so this component ¡°suspends¡±. React skips over it, and tries rendering other components in the tree.
  4. React tries to render <ProfileTimeline>. It calls resource.posts.read(). Again, there's no data yet, so this component also ¡°suspends¡±. React skips over it too, and tries rendering other components in the tree.
  5. There's nothing left to try rendering. Because <ProfileDetails> suspended, React shows the closest <Suspense> fallback above it in the tree: <h2>Loading profile...</h2>. We're done for now.
This resource object represents the data that isn't there yet, but might eventually get loaded. When we call read(), we either get the data, or the component ¡°suspends¡±. As more data streams in, React will retry rendering, and each time it might be able to progress ¡°deeper¡±. When resource.user is fetched, the <ProfileDetails> component will render successfully and we'll no longer need the <h2>Loading profile...</h2> fallback. Eventually, we'll get all the data, and there will be no fallbacks on the screen. This has an interesting implication. Even if we use a GraphQL client that collects all data requirements in a single request, streaming the response lets us show more content sooner. Because we render-as-we-fetch (as opposed to after fetching), if user appears in the response earlier than posts, we'll be able to ¡°unlock¡± the outer <Suspense> boundary before the response even finishes. We might have missed this earlier, but even the fetch-then-render solution contained a waterfall: between fetching and rendering. Suspense doesn't inherently suffer from this waterfall, and libraries like Relay take advantage of this. Note how we eliminated the if (...) ¡°is loading¡± checks from our components. This doesn't only remove boilerplate code, but it also simplifies making quick design changes. For example, if we wanted profile details and posts to always ¡°pop in¡± together, we could delete the <Suspense> boundary between them. Or we could make them independent from each other by giving each its own <Suspense> boundary. Suspense lets us change the granularity of our loading states and orchestrate their sequencing without invasive changes to our code.

Start Fetching Early

If you're working on a data fetching library, there's a crucial aspect of Render-as-You-Fetch you don't want to miss. We kick off fetching before rendering. Look at this code example closer: // Start fetching early! const resource = fetchProfileData(); // ... function ProfileDetails() { // Try to read user info const user = resource.user.read(); return <h2>{user.name}</h2>; } Try it on CodeSandbox Note that the read() call in this example doesn't start fetching. It only tries to read the data that is already being fetched. This difference is crucial to creating fast applications with Suspense. We don't want to delay loading data until a component starts rendering. As a data fetching library author, you can enforce this by making it impossible to get a resource object without also starting a fetch. Every demo on this page using our ¡°fake API¡± enforces this. You might object that fetching ¡°at the top level¡± like in this example is impractical. What are we going to do if we navigate to another profile's page? We might want to fetch based on props. The answer to this is we want to start fetching in the event handlers instead. Here is a simplified example of navigating between user's pages: // First fetch: as soon as possibleconst initialResource = fetchProfileData(0); function App() { const [resource, setResource] = useState(initialResource); return ( <> <button onClick={() => { const nextUserId = getNextId(resource.userId); // Next fetch: when the user clicks setResource(fetchProfileData(nextUserId)); }}> Next </button> <ProfilePage resource={resource} /> </> ); } Try it on CodeSandbox With this approach, we can fetch code and data in parallel. When we navigate between pages, we don't need to wait for a page's code to load to start loading its data. We can start fetching both code and data at the same time (during the link click), delivering a much better user experience. This poses a question of how do we know what to fetch before rendering the next screen. There are several ways to solve this (for example, by integrating data fetching closer with your routing solution). If you work on a data fetching library, Building Great User Experiences with Concurrent Mode and Suspense presents a deep dive on how to accomplish this and why it's important.

We're Still Figuring This Out

Suspense itself as a mechanism is flexible and doesn't have many constraints. Product code needs to be more constrained to ensure no waterfalls, but there are different ways to provide these guarantees. Some questions that we're currently exploring include:
  • Fetching early can be cumbersome to express. How do we make it easier to avoid waterfalls?
  • When we fetch data for a page, can the API encourage including data for instant transitions from it?
  • What is the lifetime of a response? Should caching be global or local? Who manages the cache?
  • Can Proxies help express lazy-loaded APIs without inserting read() calls everywhere?
  • What would the equivalent of composing GraphQL queries look like for arbitrary Suspense data?
Relay has its own answers to some of these questions. There is certainly more than a single way to do it, and we're excited to see what new ideas the React community comes up with.

Suspense and Race Conditions

Race conditions are bugs that happen due to incorrect assumptions about the order in which our code may run. Fetching data in the useEffect Hook or in class lifecycle methods like componentDidUpdate often leads to them. Suspense can help here, too ¡ª let's see how. To demonstrate the issue, we will add a top-level <App> component that renders our <ProfilePage> with a button that lets us switch between different profiles: function getNextId(id) { // ... } function App() { const [id, setId] = useState(0); return ( <> <button onClick={() => setId(getNextId(id))}> Next </button> <ProfilePage id={id} /> </> ); } Let's compare how different data fetching strategies deal with this requirement.

Race Conditions with useEffect

First, we'll try a version of our original ¡°fetch in effect¡± example. We'll modify it to pass an id parameter from the <ProfilePage> props to fetchUser(id) and fetchPosts(id): function ProfilePage({ id }) { const [user, setUser] = useState(null); useEffect(() => { fetchUser(id).then(u => setUser(u)); }, [id]); if (user === null) { return <p>Loading profile...</p>; } return ( <> <h2>{user.name}</h2> <ProfileTimeline id={id} /> </> ); } function ProfileTimeline({ id }) { const [posts, setPosts] = useState(null); useEffect(() => { fetchPosts(id).then(p => setPosts(p)); }, [id]); if (posts === null) { return <h3>Loading posts...</h3>; } return ( <ul> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } Try it on CodeSandbox Note how we also changed the effect dependencies from [] to [id] ¡ª because we want the effect to re-run when the id changes. Otherwise, we wouldn't refetch new data. If we try this code, it might seem like it works at first. However, if we randomize the delay time in our ¡°fake API¡± implementation and press the ¡°Next¡± button fast enough, we'll see from the console logs that something is going very wrong. Requests from the previous profiles may sometimes ¡°come back¡± after we've already switched the profile to another ID ¡ª and in that case they can overwrite the new state with a stale response for a different ID. This problem is possible to fix (you could use the effect cleanup function to either ignore or cancel stale requests), but it's unintuitive and difficult to debug.

Race Conditions with componentDidUpdate

One might think that this is a problem specific to useEffect or Hooks. Maybe if we port this code to classes or use convenient syntax like async / await, it will solve the problem? Let's try that: class ProfilePage extends React.Component { state = { user: null, }; componentDidMount() { this.fetchData(this.props.id); } componentDidUpdate(prevProps) { if (prevProps.id !== this.props.id) { this.fetchData(this.props.id); } } async fetchData(id) { const user = await fetchUser(id); this.setState({ user }); } render() { const { id } = this.props; const { user } = this.state; if (user === null) { return <p>Loading profile...</p>; } return ( <> <h2>{user.name}</h2> <ProfileTimeline id={id} /> </> ); } } class ProfileTimeline extends React.Component { state = { posts: null, }; componentDidMount() { this.fetchData(this.props.id); } componentDidUpdate(prevProps) { if (prevProps.id !== this.props.id) { this.fetchData(this.props.id); } } async fetchData(id) { const posts = await fetchPosts(id); this.setState({ posts }); } render() { const { posts } = this.state; if (posts === null) { return <h3>Loading posts...</h3>; } return ( <ul> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } } Try it on CodeSandbox This code is deceptively easy to read. Unfortunately, neither using a class nor the async / await syntax helped us solve this problem. This version suffers from exactly the same race conditions, for the same reasons.

The Problem

React components have their own ¡°lifecycle¡±. They may receive props or update state at any point in time. However, each asynchronous request also has its own ¡°lifecycle¡±. It starts when we kick it off, and finishes when we get a response. The difficulty we're experiencing is ¡°synchronizing¡± several processes in time that affect each other. This is hard to think about.

Solving Race Conditions with Suspense

Let's rewrite this example again, but using Suspense only: const initialResource = fetchProfileData(0); function App() { const [resource, setResource] = useState(initialResource); return ( <> <button onClick={() => { const nextUserId = getNextId(resource.userId); setResource(fetchProfileData(nextUserId)); }}> Next </button> <ProfilePage resource={resource} /> </> ); } function ProfilePage({ resource }) { return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails resource={resource} /> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline resource={resource} /> </Suspense> </Suspense> ); } function ProfileDetails({ resource }) { const user = resource.user.read(); return <h2>{user.name}</h2>; } function ProfileTimeline({ resource }) { const posts = resource.posts.read(); return ( <ul> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } Try it on CodeSandbox In the previous Suspense example, we only had one resource, so we held it in a top-level variable. Now that we have multiple resources, we moved it to the <App>'s component state: const initialResource = fetchProfileData(0); function App() { const [resource, setResource] = useState(initialResource); When we click ¡°Next¡±, the <App> component kicks off a request for the next profile, and passes that object down to the <ProfilePage> component: <> <button onClick={() => { const nextUserId = getNextId(resource.userId); setResource(fetchProfileData(nextUserId)); }}> Next </button> <ProfilePage resource={resource} /> </> Again, notice that we're not waiting for the response to set the state. It's the other way around: we set the state (and start rendering) immediately after kicking off a request. As soon as we have more data, React ¡°fills in¡± the content inside <Suspense> components. This code is very readable, but unlike the examples earlier, the Suspense version doesn't suffer from race conditions. You might be wondering why. The answer is that in the Suspense version, we don't have to think about time as much in our code. Our original code with race conditions needed to set the state at the right moment later, or otherwise it would be wrong. But with Suspense, we set the state immediately ¡ª so it's harder to mess it up.

Handling Errors

When we write code with Promises, we might use catch() to handle errors. How does this work with Suspense, given that we don't wait for Promises to start rendering? With Suspense, handling fetching errors works the same way as handling rendering errors ¡ª you can render an error boundary anywhere to ¡°catch¡± errors in components below. First, we'll define an error boundary component to use across our project: // Error boundaries currently have to be classes. class ErrorBoundary extends React.Component { state = { hasError: false, error: null }; static getDerivedStateFromError(error) { return { hasError: true, error }; } render() { if (this.state.hasError) { return this.props.fallback; } return this.props.children; } } And then we can put it anywhere in the tree to catch errors: function ProfilePage() { return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails /> <ErrorBoundary fallback={<h3>Could not fetch posts.</h3>}> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline /> </Suspense> </ErrorBoundary> </Suspense> ); } Try it on CodeSandbox It would catch both rendering errors and errors from Suspense data fetching. We can have as many error boundaries as we like but it's best to be intentional about their placement.

Next Steps

We've now covered the basics of Suspense for Data Fetching! Importantly, we now better understand why Suspense works this way, and how it fits into the data fetching space. Suspense answers some questions, but it also poses new questions of its own:
  • If some component ¡°suspends¡±, does the app freeze? How to avoid this?
  • What if we want to show a spinner in a different place than ¡°above¡± the component in a tree?
  • If we intentionally want to show an inconsistent UI for a small period of time, can we do that?
  • Instead of showing a spinner, can we add a visual effect like ¡°greying out¡± the current screen?
  • Why does our last Suspense example log a warning when clicking the ¡°Next¡± button?
To answer these questions, we will refer to the next section on Concurrent UI Patterns.

Concurrent UI Patterns (Experimental)

Caution: This page describes experimental features that are not yet available in a stable release. Don't rely on experimental builds of React in production apps. These features may change significantly and without a warning before they become a part of React. This documentation is aimed at early adopters and people who are curious. If you're new to React, don't worry about these features ¡ª you don't need to learn them right now. For example, if you're looking for a data fetching tutorial that works today, read this article instead.
Usually, when we update the state, we expect to see changes on the screen immediately. This makes sense because we want to keep our app responsive to user input. However, there are cases where we might prefer to defer an update from appearing on the screen. For example, if we switch from one page to another, and none of the code or data for the next screen has loaded yet, it might be frustrating to immediately see a blank page with a loading indicator. We might prefer to stay longer on the previous screen. Implementing this pattern has historically been difficult in React. Concurrent Mode offers a new set of tools to do that.
  • Transitions
    • Wrapping setState in a Transition
    • Adding a Pending Indicator
    • Reviewing the Changes
    • Where Does the Update Happen?
    • Transitions Are Everywhere
    • Baking Transitions Into the Design System
  • The Three Steps
    • Default: Receded ¡ú Skeleton ¡ú Complete
    • Preferred: Pending ¡ú Skeleton ¡ú Complete
    • Wrap Lazy Features in <Suspense>
    • Suspense Reveal ¡°Train¡±
    • Delaying a Pending Indicator
    • Recap
  • Other Patterns
    • Splitting High and Low Priority State
    • Deferring a Value
    • SuspenseList
  • Next Steps

Transitions

Let's revisit this demo from the previous page about Suspense for Data Fetching. When we click the ¡°Next¡± button to switch the active profile, the existing page data immediately disappears, and we see the loading indicator for the whole page again. We can call this an ¡°undesirable¡± loading state. It would be nice if we could ¡°skip¡± it and wait for some content to load before transitioning to the new screen. React offers a new built-in useTransition() Hook to help with this. We can use it in three steps. First, we'll make sure that we're actually using Concurrent Mode. We'll talk more about adopting Concurrent Mode later, but for now it's sufficient to know that we need to use ReactDOM.createRoot() rather than ReactDOM.render() for this feature to work: const rootElement = document.getElementById("root"); // Opt into Concurrent Mode ReactDOM.createRoot(rootElement).render(<App />); Next, we'll add an import for the useTransition Hook from React: import React, { useState, useTransition, Suspense } from "react"; Finally, we'll use it inside the App component: function App() { const [resource, setResource] = useState(initialResource); const [startTransition, isPending] = useTransition({ timeoutMs: 3000 }); // ... By itself, this code doesn't do anything yet. We will need to use this Hook's return values to set up our state transition. There are two values returned from useTransition:
  • startTransition is a function. We'll use it to tell React which state update we want to defer.
  • isPending is a boolean. It's React telling us whether that transition is ongoing at the moment.
We will use them right below. Note we passed a configuration object to useTransition. Its timeoutMs property specifies how long we're willing to wait for the transition to finish. By passing {timeoutMs: 3000}, we say ¡°If the next profile takes more than 3 seconds to load, show the big spinner ¡ª but before that timeout it's okay to keep showing the previous screen¡±.

Wrapping setState in a Transition

Our ¡°Next¡± button click handler sets the state that switches the current profile in the state: <button onClick={() => { const nextUserId = getNextId(resource.userId); setResource(fetchProfileData(nextUserId)); }} > We'll wrap that state update into startTransition. That's how we tell React we don't mind React delaying that state update if it leads to an undesirable loading state: <button onClick={() => { startTransition(() => { const nextUserId = getNextId(resource.userId); setResource(fetchProfileData(nextUserId)); }); }} > Try it on CodeSandbox Press ¡°Next¡± a few times. Notice it already feels very different. Instead of immediately seeing an empty screen on click, we now keep seeing the previous page for a while. When the data has loaded, React transitions us to the new screen. If we make our API responses take 5 seconds, we can confirm that now React ¡°gives up¡± and transitions anyway to the next screen after 3 seconds. This is because we passed {timeoutMs: 3000} to useTransition(). For example, if we passed {timeoutMs: 60000} instead, it would wait a whole minute.

Adding a Pending Indicator

There's still something that feels broken about our last example. Sure, it's nice not to see a ¡°bad¡± loading state. But having no indication of progress at all feels even worse! When we click ¡°Next¡±, nothing happens and it feels like the app is broken. Our useTransition() call returns two values: startTransition and isPending. const [startTransition, isPending] = useTransition({ timeoutMs: 3000 }); We've already used startTransition to wrap the state update. Now we're going to use isPending too. React gives this boolean to us so we can tell whether we're currently waiting for this transition to finish. We'll use it to indicate that something is happening: return ( <> <button disabled={isPending} onClick={() => { startTransition(() => { const nextUserId = getNextId(resource.userId); setResource(fetchProfileData(nextUserId)); }); }} > Next </button> {isPending ? " Loading..." : null} <ProfilePage resource={resource} /> </> ); Try it on CodeSandbox Now, this feels a lot better! When we click Next, it gets disabled because clicking it multiple times doesn't make sense. And the new ¡°Loading¡­¡± tells the user that the app didn't freeze.

Reviewing the Changes

Let's take another look at all the changes we've made since the original example: function App() { const [resource, setResource] = useState(initialResource); const [startTransition, isPending] = useTransition({ timeoutMs: 3000 }); return ( <> <button disabled={isPending} onClick={() => { startTransition(() => { const nextUserId = getNextId(resource.userId); setResource(fetchProfileData(nextUserId)); }); }} > Next </button> {isPending ? " Loading..." : null} <ProfilePage resource={resource} /> </> ); } Try it on CodeSandbox It took us only seven lines of code to add this transition:
  • We've imported the useTransition Hook and used it in the component that updates the state.
  • We've passed {timeoutMs: 3000} to stay on the previous screen for at most 3 seconds.
  • We've wrapped our state update into startTransition to tell React it's okay to delay it.
  • We're using isPending to communicate the state transition progress to the user and to disable the button.
As a result, clicking ¡°Next¡± doesn't perform an immediate state transition to an ¡°undesirable¡± loading state, but instead stays on the previous screen and communicates progress there.

Where Does the Update Happen?

This wasn't very difficult to implement. However, if you start thinking about how this could possibly work, it might become a little mindbending. If we set the state, how come we don't see the result right away? Where is the next <ProfilePage> rendering? Clearly, both ¡°versions¡± of <ProfilePage> exist at the same time. We know the old one exists because we see it on the screen and even display a progress indicator on it. And we know the new version also exists somewhere, because it's the one that we're waiting for! But how can two versions of the same component exist at the same time? This gets at the root of what Concurrent Mode is. We've previously said it's a bit like React working on state update on a ¡°branch¡±. Another way we can conceptualize is that wrapping a state update in startTransition begins rendering it ¡°in a different universe¡±, much like in science fiction movies. We don't ¡°see¡± that universe directly ¡ª but we can get a signal from it that tells us something is happening (isPending). When the update is ready, our ¡°universes¡± merge back together, and we see the result on the screen! Play a bit more with the demo, and try to imagine it happening. Of course, two versions of the tree rendering at the same time is an illusion, just like the idea that all programs run on your computer at the same time is an illusion. An operating system switches between different applications very fast. Similarly, React can switch between the version of the tree you see on the screen and the version that it's ¡°preparing¡± to show next. An API like useTransition lets you focus on the desired user experience, and not think about the mechanics of how it's implemented. Still, it can be a helpful metaphor to imagine that updates wrapped in startTransition happen ¡°on a branch¡± or ¡°in a different world¡±.

Transitions Are Everywhere

As we learned from the Suspense walkthrough, any component can ¡°suspend¡± any time if some data it needs is not ready yet. We can strategically place <Suspense> boundaries in different parts of the tree to handle this, but it won't always be enough. Let's get back to our first Suspense demo where there was just one profile. Currently, it fetches the data only once. We'll add a ¡°Refresh¡± button to check for server updates. Our first attempt might look like this: const initialResource = fetchUserAndPosts(); function ProfilePage() { const [resource, setResource] = useState(initialResource); function handleRefreshClick() { setResource(fetchUserAndPosts()); } return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails resource={resource} /> <button onClick={handleRefreshClick}> Refresh </button> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline resource={resource} /> </Suspense> </Suspense> ); } Try it on CodeSandbox In this example, we start data fetching at the load and every time you press ¡°Refresh¡±. We put the result of calling fetchUserAndPosts() into state so that components below can start reading the new data from the request we just kicked off. We can see in this example that pressing ¡°Refresh¡± works. The <ProfileDetails> and <ProfileTimeline> components receive a new resource prop that represents the fresh data, they ¡°suspend¡± because we don't have a response yet, and we see the fallbacks. When the response loads, we can see the updated posts (our fake API adds them every 3 seconds). However, the experience feels really jarring. We were browsing a page, but it got replaced by a loading state right as we were interacting with it. It's disorienting. Just like before, to avoid showing an undesirable loading state, we can wrap the state update in a transition: function ProfilePage() { const [startTransition, isPending] = useTransition({ // Wait 10 seconds before fallback timeoutMs: 10000 }); const [resource, setResource] = useState(initialResource); function handleRefreshClick() { startTransition(() => { setResource(fetchProfileData()); }); } return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails resource={resource} /> <button onClick={handleRefreshClick} disabled={isPending} > {isPending ? "Refreshing..." : "Refresh"} </button> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline resource={resource} /> </Suspense> </Suspense> ); } Try it on CodeSandbox This feels a lot better! Clicking ¡°Refresh¡± doesn't pull us away from the page we're browsing anymore. We see something is loading ¡°inline¡±, and when the data is ready, it's displayed.

Baking Transitions Into the Design System

We can now see that the need for useTransition is very common. Pretty much any button click or interaction that can lead to a component suspending needs to be wrapped in useTransition to avoid accidentally hiding something the user is interacting with. This can lead to a lot of repetitive code across components. This is why we generally recommend to bake useTransition into the design system components of your app. For example, we can extract the transition logic into our own <Button> component: function Button({ children, onClick }) { const [startTransition, isPending] = useTransition({ timeoutMs: 10000 }); function handleClick() { startTransition(() => { onClick(); }); } const spinner = ( // ... ); return ( <> <button onClick={handleClick} disabled={isPending} > {children} </button> {isPending ? spinner : null} </> ); } Try it on CodeSandbox Note that the button doesn't care what state we're updating. It's wrapping any state updates that happen during its onClick handler into a transition. Now that our <Button> takes care of setting up the transition, the <ProfilePage> component doesn't need to set up its own: function ProfilePage() { const [resource, setResource] = useState(initialResource); function handleRefreshClick() { setResource(fetchProfileData()); } return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails resource={resource} /> <Button onClick={handleRefreshClick}> Refresh </Button> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline resource={resource} /> </Suspense> </Suspense> ); } Try it on CodeSandbox When a button gets clicked, it starts a transition and calls props.onClick() inside of it ¡ª which triggers handleRefreshClick in the <ProfilePage> component. We start fetching the fresh data, but it doesn't trigger a fallback because we're inside a transition, and the 10 second timeout specified in the useTransition call hasn't passed yet. While a transition is pending, the button displays an inline loading indicator. We can see now how Concurrent Mode helps us achieve a good user experience without sacrificing isolation and modularity of components. React coordinates the transition.

The Three Steps

By now we have discussed all of the different visual states that an update may go through. In this section, we will give them names and talk about the progression between them. At the very end, we have the Complete state. That's where we want to eventually get to. It represents the moment when the next screen is fully rendered and isn't loading more data. But before our screen can be Complete, we might need to load some data or code. When we're on the next screen, but some parts of it are still loading, we call that a Skeleton state. Finally, there are two primary ways that lead us to the Skeleton state. We will illustrate the difference between them with a concrete example.

Default: Receded ¡ú Skeleton ¡ú Complete

Open this example and click ¡°Open Profile¡±. You will see several visual states one by one:
  • Receded: For a second, you will see the <h2>Loading the app...</h2> fallback.
  • Skeleton: You will see the <ProfilePage> component with <h3>Loading posts...</h3> inside.
  • Complete: You will see the <ProfilePage> component with no fallbacks inside. Everything was fetched.
How do we separate the Receded and the Skeleton states? The difference between them is that the Receded state feels like ¡°taking a step back¡± to the user, while the Skeleton state feels like ¡°taking a step forward¡± in our progress to show more content. In this example, we started our journey on the <HomePage>: <Suspense fallback={...}> {/* previous screen */} <HomePage /> </Suspense> After the click, React started rendering the next screen: <Suspense fallback={...}> {/* next screen */} <ProfilePage> <ProfileDetails /> <Suspense fallback={...}> <ProfileTimeline /> </Suspense> </ProfilePage> </Suspense> Both <ProfileDetails> and <ProfileTimeline> need data to render, so they suspend: <Suspense fallback={...}> {/* next screen */} <ProfilePage> <ProfileDetails /> {/* suspends! */} <Suspense fallback={<h3>Loading posts...</h3>}> <ProfileTimeline /> {/* suspends! */} </Suspense> </ProfilePage> </Suspense> When a component suspends, React needs to show the closest fallback. But the closest fallback to <ProfileDetails> is at the top level: <Suspense fallback={ // We see this fallback now because of <ProfileDetails> <h2>Loading the app...</h2>}> {/* next screen */} <ProfilePage> <ProfileDetails /> {/* suspends! */} <Suspense fallback={...}> <ProfileTimeline /> </Suspense> </ProfilePage> </Suspense> This is why when we click the button, it feels like we've ¡°taken a step back¡±. The <Suspense> boundary which was previously showing useful content (<HomePage />) had to ¡°recede¡± to showing the fallback (<h2>Loading the app...</h2>). We call that a Receded state. As we load more data, React will retry rendering, and <ProfileDetails> can render successfully. Finally, we're in the Skeleton state. We see the new page with missing parts: <Suspense fallback={...}> {/* next screen */} <ProfilePage> <ProfileDetails /> <Suspense fallback={ // We see this fallback now because of <ProfileTimeline> <h3>Loading posts...</h3> }> <ProfileTimeline /> {/* suspends! */} </Suspense> </ProfilePage> </Suspense> Eventually, they load too, and we get to the Complete state. This scenario (Receded ¡ú Skeleton ¡ú Complete) is the default one. However, the Receded state is not very pleasant because it ¡°hides¡± existing information. This is why React lets us opt into a different sequence (Pending ¡ú Skeleton ¡ú Complete) with useTransition.

Preferred: Pending ¡ú Skeleton ¡ú Complete

When we useTransition, React will let us ¡°stay¡± on the previous screen ¡ª and show a progress indicator there. We call that a Pending state. It feels much better than the Receded state because none of our existing content disappears, and the page stays interactive. You can compare these two examples to feel the difference:
  • Default: Receded ¡ú Skeleton ¡ú Complete
  • Preferred: Pending ¡ú Skeleton ¡ú Complete
The only difference between these two examples is that the first uses regular <button>s, but the second one uses our custom <Button> component with useTransition.

Wrap Lazy Features in <Suspense>

Open this example. When you press a button, you'll see the Pending state for a second before moving on. This transition feels nice and fluid. We will now add a brand new feature to the profile page ¡ª a list of fun facts about a person: function ProfilePage({ resource }) { return ( <> <ProfileDetails resource={resource} /> <Suspense fallback={<h3>Loading posts...</h3>}> <ProfileTimeline resource={resource} /> </Suspense> <ProfileTrivia resource={resource} /> </> ); } function ProfileTrivia({ resource }) { const trivia = resource.trivia.read(); return ( <> <h3>Fun Facts</h3> <ul> {trivia.map(fact => ( <li key={fact.id}>{fact.text}</li> ))} </ul> </> );} Try it on CodeSandbox If you press ¡°Open Profile¡± now, you can tell something is wrong. It takes a whole seven seconds to make the transition now! This is because our trivia API is too slow. Let's say we can't make the API faster. How can we improve the user experience with this constraint? If we don't want to stay in the Pending state for too long, our first instinct might be to set timeoutMs in useTransition to something smaller, like 3000. You can try this here. This lets us escape the prolonged Pending state, but we still don't have anything useful to show! There is a simpler way to solve this. Instead of making the transition shorter, we can ¡°disconnect¡± the slow component from the transition by wrapping it into <Suspense>: function ProfilePage({ resource }) { return ( <> <ProfileDetails resource={resource} /> <Suspense fallback={<h3>Loading posts...</h3>}> <ProfileTimeline resource={resource} /> </Suspense> <Suspense fallback={<h3>Loading fun facts...</h3>}> <ProfileTrivia resource={resource} /> </Suspense> </> ); } Try it on CodeSandbox This reveals an important insight. React always prefers to go to the Skeleton state as soon as possible. Even if we use transitions with long timeouts everywhere, React will not stay in the Pending state for longer than necessary to avoid the Receded state. If some feature isn't a vital part of the next screen, wrap it in <Suspense> and let it load lazily. This ensures we can show the rest of the content as soon as possible. Conversely, if a screen is not worth showing without some component, such as <ProfileDetails> in our example, do not wrap it in <Suspense>. Then the transitions will ¡°wait¡± for it to be ready.

Suspense Reveal ¡°Train¡±

When we're already on the next screen, sometimes the data needed to ¡°unlock¡± different <Suspense> boundaries arrives in quick succession. For example, two different responses might arrive after 1000ms and 1050ms, respectively. If you've already waited for a second, waiting another 50ms is not going to be perceptible. This is why React reveals <Suspense> boundaries on a schedule, like a ¡°train¡± that arrives periodically. This trades a small delay for reducing the layout thrashing and the number of visual changes presented to the user. You can see a demo of this here. The ¡°posts¡± and ¡°fun facts¡± responses come within 100ms of each other. But React coalesces them and ¡°reveals¡± their Suspense boundaries together.

Delaying a Pending Indicator

Our Button component will immediately show the Pending state indicator on click: function Button({ children, onClick }) { const [startTransition, isPending] = useTransition({ timeoutMs: 10000 }); // ... return ( <> <button onClick={handleClick} disabled={isPending}> {children} </button> {isPending ? spinner : null} </> ); } Try it on CodeSandbox This signals to the user that some work is happening. However, if the transition is relatively short (less than 500ms), it might be too distracting and make the transition itself feel slower. One possible solution to this is to delay the spinner itself from displaying: .DelayedSpinner { animation: 0s linear 0.5s forwards makeVisible; visibility: hidden; } @keyframes makeVisible { to { visibility: visible; } } const spinner = ( <span className="DelayedSpinner"> {/* ... */} </span>); return ( <> <button onClick={handleClick}>{children}</button> {isPending ? spinner : null} </> ); Try it on CodeSandbox With this change, even though we're in the Pending state, we don't display any indication to the user until 500ms has passed. This may not seem like much of an improvement when the API responses are slow. But compare how it feels before and after when the API call is fast. Even though the rest of the code hasn't changed, suppressing a ¡°too fast¡± loading state improves the perceived performance by not calling attention to the delay.

Recap

The most important things we learned so far are:
  • By default, our loading sequence is Receded ¡ú Skeleton ¡ú Complete.
  • The Receded state doesn't feel very nice because it hides existing content.
  • With useTransition, we can opt into showing a Pending state first instead. This will keep us on the previous screen while the next screen is being prepared.
  • If we don't want some component to delay the transition, we can wrap it in its own <Suspense> boundary.
  • Instead of doing useTransition in every other component, we can build it into our design system.

Other Patterns

Transitions are probably the most common Concurrent Mode pattern you'll encounter, but there are a few more patterns you might find useful.

Splitting High and Low Priority State

When you design React components, it is usually best to find the ¡°minimal representation¡± of state. For example, instead of keeping firstName, lastName, and fullName in state, it's usually better keep only firstName and lastName, and then calculate fullName during rendering. This lets us avoid mistakes where we update one state but forget the other state. However, in Concurrent Mode there are cases where you might want to ¡°duplicate¡± some data in different state variables. Consider this tiny translation app: const initialQuery = "Hello, world"; const initialResource = fetchTranslation(initialQuery); function App() { const [query, setQuery] = useState(initialQuery); const [resource, setResource] = useState(initialResource); function handleChange(e) { const value = e.target.value; setQuery(value); setResource(fetchTranslation(value)); } return ( <> <input value={query} onChange={handleChange} /> <Suspense fallback={<p>Loading...</p>}> <Translation resource={resource} /> </Suspense> </> ); } function Translation({ resource }) { return ( <p> <b>{resource.read()}</b> </p> ); } Try it on CodeSandbox Notice how when you type into the input, the <Translation> component suspends, and we see the <p>Loading...</p> fallback until we get fresh results. This is not ideal. It would be better if we could see the previous translation for a bit while we're fetching the next one. In fact, if we open the console, we'll see a warning: Warning: App triggered a user-blocking update that suspended. The fix is to split the update into multiple parts: a user-blocking update to provide immediate feedback, and another update that triggers the bulk of the changes. Refer to the documentation for useTransition to learn how to implement this pattern. As we mentioned earlier, if some state update causes a component to suspend, that state update should be wrapped in a transition. Let's add useTransition to our component: function App() { const [query, setQuery] = useState(initialQuery); const [resource, setResource] = useState(initialResource); const [startTransition, isPending] = useTransition({ timeoutMs: 5000 }); function handleChange(e) { const value = e.target.value; startTransition(() => { setQuery(value); setResource(fetchTranslation(value)); }); } // ... } Try it on CodeSandbox Try typing into the input now. Something's wrong! The input is updating very slowly. We've fixed the first problem (suspending outside of a transition). But now because of the transition, our state doesn't update immediately, and it can't ¡°drive¡± a controlled input! The answer to this problem is to split the state in two parts: a ¡°high priority¡± part that updates immediately, and a ¡°low priority¡± part that may wait for a transition. In our example, we already have two state variables. The input text is in query, and we read the translation from resource. We want changes to the query state to happen immediately, but changes to the resource (i.e. fetching a new translation) should trigger a transition. So the correct fix is to put setQuery (which doesn't suspend) outside the transition, but setResource (which will suspend) inside of it. function handleChange(e) { const value = e.target.value; // Outside the transition (urgent) setQuery(value); startTransition(() => { // Inside the transition (may be delayed) setResource(fetchTranslation(value)); }); } Try it on CodeSandbox With this change, it works as expected. We can type into the input immediately, and the translation later ¡°catches up¡± to what we have typed.

Deferring a Value

By default, React always renders a consistent UI. Consider code like this: <> <ProfileDetails user={user} /> <ProfileTimeline user={user} /> </> React guarantees that whenever we look at these components on the screen, they will reflect data from the same user. If a different user is passed down because of a state update, you would see them changing together. You can't ever record a screen and find a frame where they would show values from different users. (If you ever run into a case like this, file a bug!) This makes sense in the vast majority of situations. Inconsistent UI is confusing and can mislead users. (For example, it would be terrible if a messenger's Send button and the conversation picker pane ¡°disagreed¡± about which thread is currently selected.) However, sometimes it might be helpful to intentionally introduce an inconsistency. We could do it manually by ¡°splitting¡± the state like above, but React also offers a built-in Hook for this: import { useDeferredValue } from 'react'; const deferredValue = useDeferredValue(value, { timeoutMs: 5000 }); To demonstrate this feature, we'll use the profile switcher example. Click the ¡°Next¡± button and notice how it takes 1 second to do a transition. Let's say that fetching the user details is very fast and only takes 300 milliseconds. Currently, we're waiting a whole second because we need both user details and posts to display a consistent profile page. But what if we want to show the details faster? If we're willing to sacrifice consistency, we could pass potentially stale data to the components that delay our transition. That's what useDeferredValue() lets us do: function ProfilePage({ resource }) { const deferredResource = useDeferredValue(resource, { timeoutMs: 1000 }); return ( <Suspense fallback={<h2>Loading profile...</h2>}> <ProfileDetails resource={resource} /> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline resource={deferredResource} isStale={deferredResource !== resource} /> </Suspense> </Suspense> ); } function ProfileTimeline({ isStale, resource }) { const posts = resource.posts.read(); return ( <ul style={{ opacity: isStale ? 0.7 : 1 }}> {posts.map(post => ( <li key={post.id}>{post.text}</li> ))} </ul> ); } Try it on CodeSandbox The tradeoff we're making here is that <ProfileTimeline> will be inconsistent with other components and potentially show an older item. Click ¡°Next¡± a few times, and you'll notice it. But thanks to that, we were able to cut down the transition time from 1000ms to 300ms. Whether or not it's an appropriate tradeoff depends on the situation. But it's a handy tool, especially when the content doesn't change noticeably between items, and the user might not even realize they were looking at a stale version for a second. It's worth noting that useDeferredValue is not only useful for data fetching. It also helps when an expensive component tree causes an interaction (e.g. typing in an input) to be sluggish. Just like we can ¡°defer¡± a value that takes too long to fetch (and show its old value despite other components updating), we can do this with trees that take too long to render. For example, consider a filterable list like this: function App() { const [text, setText] = useState("hello"); function handleChange(e) { setText(e.target.value); } return ( <div className="App"> <label> Type into the input:{" "} <input value={text} onChange={handleChange} /> </label> ... <MySlowList text={text} /> </div> ); } Try it on CodeSandbox In this example, every item in <MySlowList> has an artificial slowdown ¡ª each of them blocks the thread for a few milliseconds. We'd never do this in a real app, but this helps us simulate what can happen in a deep component tree with no single obvious place to optimize. We can see how typing in the input causes stutter. Now let's add useDeferredValue: function App() { const [text, setText] = useState("hello"); const deferredText = useDeferredValue(text, { timeoutMs: 5000 }); function handleChange(e) { setText(e.target.value); } return ( <div className="App"> <label> Type into the input:{" "} <input value={text} onChange={handleChange} /> </label> ... <MySlowList text={deferredText} /> </div> ); } Try it on CodeSandbox Now typing has a lot less stutter ¡ª although we pay for this by showing the results with a lag. How is this different from debouncing? Our example has a fixed artificial delay (3ms for every one of 80 items), so there is always a delay, no matter how fast our computer is. However, the useDeferredValue value only ¡°lags behind¡± if the rendering takes a while. There is no minimal lag imposed by React. With a more realistic workload, you can expect the lag to adjust to the user's device. On fast machines, the lag would be smaller or non-existent, and on slow machines, it would be more noticeable. In both cases, the app would remain responsive. That's the advantage of this mechanism over debouncing or throttling, which always impose a minimal delay and can't avoid blocking the thread while rendering. Even though there is an improvement in responsiveness, this example isn't as compelling yet because Concurrent Mode is missing some crucial optimizations for this use case. Still, it is interesting to see that features like useDeferredValue (or useTransition) are useful regardless of whether we're waiting for network or for computational work to finish.

SuspenseList

<SuspenseList> is the last pattern that's related to orchestrating loading states. Consider this example: function ProfilePage({ resource }) { return ( <> <ProfileDetails resource={resource} /> <Suspense fallback={<h3>Loading posts...</h3>}> <ProfileTimeline resource={resource} /> </Suspense> <Suspense fallback={<h3>Loading fun facts...</h3>}> <ProfileTrivia resource={resource} /> </Suspense> </> ); } Try it on CodeSandbox The API call duration in this example is randomized. If you keep refreshing it, you will notice that sometimes the posts arrive first, and sometimes the ¡°fun facts¡± arrive first. This presents a problem. If the response for fun facts arrives first, we'll see the fun facts below the <h3>Loading posts...</h3> fallback for posts. We might start reading them, but then the posts response will come back, and shift all the facts down. This is jarring. One way we could fix it is by putting them both in a single boundary: <Suspense fallback={<h3>Loading posts and fun facts...</h3>}> <ProfileTimeline resource={resource} /> <ProfileTrivia resource={resource} /> </Suspense> Try it on CodeSandbox The problem with this is that now we always wait for both of them to be fetched. However, if it's the posts that came back first, there's no reason to delay showing them. When fun facts load later, they won't shift the layout because they're already below the posts. Other approaches to this, such as composing Promises in a special way, are increasingly difficult to pull off when the loading states are located in different components down the tree. To solve this, we will import SuspenseList: import { SuspenseList } from 'react'; <SuspenseList> coordinates the ¡°reveal order¡± of the closest <Suspense> nodes below it: function ProfilePage({ resource }) { return ( <SuspenseList revealOrder="forwards"> <ProfileDetails resource={resource} /> <Suspense fallback={<h3>Loading posts...</h3>}> <ProfileTimeline resource={resource} /> </Suspense> <Suspense fallback={<h3>Loading fun facts...</h3>}> <ProfileTrivia resource={resource} /> </Suspense> </SuspenseList> ); } Try it on CodeSandbox The revealOrder="forwards" option means that the closest <Suspense> nodes inside this list will only ¡°reveal¡± their content in the order they appear in the tree ¡ª even if the data for them arrives in a different order. <SuspenseList> has other interesting modes: try changing "forwards" to "backwards" or "together" and see what happens. You can control how many loading states are visible at once with the tail prop. If we specify tail="collapsed", we'll see at most one fallback at a time. You can play with it here. Keep in mind that <SuspenseList> is composable, like anything in React. For example, you can create a grid by putting several <SuspenseList> rows inside a <SuspenseList> table.

Next Steps

Concurrent Mode offers a powerful UI programming model and a set of new composable primitives to help you orchestrate delightful user experiences. It's a result of several years of research and development, but it's not finished. In the section on adopting Concurrent Mode, we'll describe how you can try it and what you can expect.

Adopting Concurrent Mode (Experimental)

Caution: This page describes experimental features that are not yet available in a stable release. Don't rely on experimental builds of React in production apps. These features may change significantly and without a warning before they become a part of React. This documentation is aimed at early adopters and people who are curious. If you're new to React, don't worry about these features ¡ª you don't need to learn them right now.
  • Installation
    • Who Is This Experimental Release For?
    • Enabling Concurrent Mode
  • What to Expect
    • Migration Step: Blocking Mode
    • Why So Many Modes?
    • Feature Comparison

Installation

Concurrent Mode is only available in the experimental builds of React. To install them, run: npm install react@experimental react-dom@experimental There are no semantic versioning guarantees for the experimental builds.
APIs may be added, changed, or removed with any @experimental release. Experimental releases will have frequent breaking changes. You can try these builds on personal projects or in a branch, but we don't recommend running them in production. At Facebook, we do run them in production, but that's because we're also there to fix bugs when something breaks. You've been warned!

Who Is This Experimental Release For?

This release is primarily aimed at early adopters, library authors, and curious people. We're using this code in production (and it works for us) but there are still some bugs, missing features, and gaps in the documentation. We'd like to hear more about what breaks in Concurrent Mode so we can better prepare it for an official stable release in the future.

Enabling Concurrent Mode

Normally, when we add features to React, you can start using them immediately. Fragments, Context, and even Hooks are examples of such features. You can use them in new code without making any changes to the existing code. Concurrent Mode is different. It introduces semantic changes to how React works. Otherwise, the new features enabled by it wouldn't be possible. This is why they're grouped into a new ¡°mode¡± rather than released one by one in isolation. You can't opt into Concurrent Mode on a per-subtree basis. Instead, to opt in, you have to do it in the place where today you call ReactDOM.render(). This will enable Concurrent Mode for the whole <App /> tree: import ReactDOM from 'react-dom'; // If you previously had: // // ReactDOM.render(<App />, document.getElementById('root')); // // You can opt into Concurrent Mode by writing: ReactDOM.unstable_createRoot( document.getElementById('root') ).render(<App />);
Note: Concurrent Mode APIs such as createRoot only exist in the experimental builds of React.
In Concurrent Mode, the lifecycle methods previously marked as ¡°unsafe¡± actually are unsafe, and lead to bugs even more than in today's React. We don't recommend trying Concurrent Mode until your app is Strict Mode-compatible.

What to Expect

If you have a large existing app, or if your app depends on a lot of third-party packages, please don't expect that you can use the Concurrent Mode immediately. For example, at Facebook we are using Concurrent Mode for the new website, but we're not planning to enable it on the old website. This is because our old website still uses unsafe lifecycle methods in the product code, incompatible third-party libraries, and patterns that don't work well with the Concurrent Mode. In our experience, code that uses idiomatic React patterns and doesn't rely on external state management solutions is the easiest to get running in the Concurrent Mode. We will describe common problems we've seen and the solutions to them separately in the coming weeks.

Migration Step: Blocking Mode

For older codebases, Concurrent Mode might be a step too far. This is why we also provide a new ¡°Blocking Mode¡± in the experimental React builds. You can try it by substituting createRoot with createBlockingRoot. It only offers a small subset of the Concurrent Mode features, but it is closer to how React works today and can serve as a migration step. To recap:
  • Legacy Mode: ReactDOM.render(<App />, rootNode). This is what React apps use today. There are no plans to remove the legacy mode in the observable future ¡ª but it won't be able to support these new features.
  • Blocking Mode: ReactDOM.createBlockingRoot(rootNode).render(<App />). It is currently experimental. It is intended as a first migration step for apps that want to get a subset of Concurrent Mode features.
  • Concurrent Mode: ReactDOM.createRoot(rootNode).render(<App />). It is currently experimental. In the future, after it stabilizes, we intend to make it the default React mode. This mode enables all the new features.

Why So Many Modes?

We think it is better to offer a gradual migration strategy than to make huge breaking changes ¡ª or to let React stagnate into irrelevance. In practice, we expect that most apps using Legacy Mode today should be able to migrate at least to the Blocking Mode (if not Concurrent Mode). This fragmentation can be annoying for libraries that aim to support all Modes in the short term. However, gradually moving the ecosystem away from the Legacy Mode will also solve problems that affect major libraries in the React ecosystem, such as confusing Suspense behavior when reading layout and lack of consistent batching guarantees. There's a number of bugs that can't be fixed in Legacy Mode without changing semantics, but don't exist in Blocking and Concurrent Modes. You can think of the Blocking Mode as a ¡°gracefully degraded¡± version of the Concurrent Mode. As a result, in longer term we should be able to converge and stop thinking about different Modes altogether. But for now, Modes are an important migration strategy. They let everyone decide when a migration is worth it, and upgrade at their own pace.

Feature Comparison

Legacy Mode Blocking Mode Concurrent Mode
String Refs ** **
Legacy Context ** **
findDOMNode ** **
Suspense
SuspenseList
Suspense SSR + Hydration
Progressive Hydration
Selective Hydration
Cooperative Multitasking
Automatic batching of multiple setStates *
Priority-based Rendering
Interruptible Prerendering
useTransition
useDeferredValue
Suspense Reveal ¡°Train¡±
*: Legacy mode has automatic batching in React-managed events but it's limited to one browser task. Non-React events must opt-in using unstable_batchedUpdates. In Blocking Mode and Concurrent Mode, all setStates are batched by default. **: Warns in development.

Concurrent Mode API Reference (Experimental)

Caution: This page describes experimental features that are not yet available in a stable release. Don't rely on experimental builds of React in production apps. These features may change significantly and without a warning before they become a part of React. This documentation is aimed at early adopters and people who are curious. If you're new to React, don't worry about these features ¡ª you don't need to learn them right now.
This page is an API reference for the React Concurrent Mode. If you're looking for a guided introduction instead, check out Concurrent UI Patterns. Note: This is a Community Preview and not the final stable version. There will likely be future changes to these APIs. Use at your own risk!
  • Enabling Concurrent Mode
    • createRoot
    • createBlockingRoot
  • Suspense
    • Suspense
    • SuspenseList
    • useTransition
    • useDeferredValue

Enabling Concurrent Mode

createRoot

ReactDOM.createRoot(rootNode).render(<App />); Replaces ReactDOM.render(<App />, rootNode) and enables Concurrent Mode. For more information on Concurrent Mode, check out the Concurrent Mode documentation.

createBlockingRoot

ReactDOM.createBlockingRoot(rootNode).render(<App />) Replaces ReactDOM.render(<App />, rootNode) and enables Blocking Mode. Opting into Concurrent Mode introduces semantic changes to how React works. This means that you can't use Concurrent Mode in just a few components. Because of this, some apps may not be able to migrate directly to Concurrent Mode. Blocking Mode only contains a small subset of Concurrent Mode features and is intended as an intermediary migration step for apps that are unable to migrate directly.

Suspense API

Suspense

<Suspense fallback={<h2>Loading...</h2>}> <ProfilePhoto /> <ProfileDetails /> </Suspense> Suspense lets your components ¡°wait¡± for something before they can render, showing a fallback while waiting. In this example, ProfileDetails is waiting for an asynchronous API call to fetch some data. While we wait for ProfileDetails and ProfilePhoto, we will show the Loading... fallback instead. It is important to note that until all children inside <Suspense> has loaded, we will continue to show the fallback. Suspense takes two props:
  • fallback takes a loading indicator. The fallback is shown until all of the children of the Suspense component have finished rendering.
  • unstable_avoidThisFallback takes a boolean. It tells React whether to ¡°skip¡± revealing this boundary during the initial load. This API will likely be removed in a future release.

<SuspenseList>

<SuspenseList revealOrder="forwards"> <Suspense fallback={'Loading...'}> <ProfilePicture id={1} /> </Suspense> <Suspense fallback={'Loading...'}> <ProfilePicture id={2} /> </Suspense> <Suspense fallback={'Loading...'}> <ProfilePicture id={3} /> </Suspense> ... </SuspenseList> SuspenseList helps coordinate many components that can suspend by orchestrating the order in which these components are revealed to the user. When multiple components need to fetch data, this data may arrive in an unpredictable order. However, if you wrap these items in a SuspenseList, React will not show an item in the list until previous items have been displayed (this behavior is adjustable). SuspenseList takes two props:
  • revealOrder (forwards, backwards, together) defines the order in which the SuspenseList children should be revealed.
    • together reveals all of them when they're ready instead of one by one.
  • tail (collapsed, hidden) dictates how unloaded items in a SuspenseList is shown.
    • By default, SuspenseList will show all fallbacks in the list.
    • collapsed shows only the next fallback in the list.
    • hidden doesn't show any unloaded items.
Note that SuspenseList only operates on the closest Suspense and SuspenseList components below it. It does not search for boundaries deeper than one level. However, it is possible to nest multiple SuspenseList components in each other to build grids.

useTransition

const SUSPENSE_CONFIG = { timeoutMs: 2000 }; const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG); useTransition allows components to avoid undesirable loading states by waiting for content to load before transitioning to the next screen. It also allows components to defer slower, data fetching updates until subsequent renders so that more crucial updates can be rendered immediately. The useTransition hook returns two values in an array.
  • startTransition is a function that takes a callback. We can use it to tell React which state we want to defer.
  • isPending is a boolean. It's React's way of informing us whether we're waiting for the transition to finish.
If some state update causes a component to suspend, that state update should be wrapped in a transition. const SUSPENSE_CONFIG = { timeoutMs: 2000 }; function App() { const [resource, setResource] = useState(initialResource); const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG); return ( <> <button disabled={isPending} onClick={() => { startTransition(() => { const nextUserId = getNextId(resource.userId); setResource(fetchProfileData(nextUserId)); }); }} > Next </button> {isPending ? " Loading..." : null} <Suspense fallback={<Spinner />}> <ProfilePage resource={resource} /> </Suspense> </> ); } In this code, we've wrapped our data fetching with startTransition. This allows us to start fetching the profile data right away, while deferring the render of the next profile page and its associated Spinner for 2 seconds (the time shown in timeoutMs). The isPending boolean lets React know that our component is transitioning, so we are able to let the user know this by showing some loading text on the previous profile page. For an in-depth look at transitions, you can read Concurrent UI Patterns.
useTransition Config
const SUSPENSE_CONFIG = { timeoutMs: 2000 }; useTransition accepts an optional Suspense Config with a timeoutMs. This timeout (in milliseconds) tells React how long to wait before showing the next state (the new Profile Page in the above example). Note: We recommend that you share Suspense Config between different modules.

useDeferredValue

const deferredValue = useDeferredValue(value, { timeoutMs: 2000 }); Returns a deferred version of the value that may ¡°lag behind¡± it for at most timeoutMs. This is commonly used to keep the interface responsive when you have something that renders immediately based on user input and something that needs to wait for a data fetch. A good example of this is a text input. function App() { const [text, setText] = useState("hello"); const deferredText = useDeferredValue(text, { timeoutMs: 2000 }); return ( <div className="App"> {/* Keep passing the current text to the input */} <input value={text} onChange={handleChange} /> ... {/* But the list is allowed to "lag behind" when necessary */} <MySlowList text={deferredText} /> </div> ); } This allows us to start showing the new text for the input immediately, which allows the webpage to feel responsive. Meanwhile, MySlowList ¡°lags behind¡± for up to 2 seconds according to the timeoutMs before updating, allowing it to render with the current text in the background. For an in-depth look at deferring values, you can read Concurrent UI Patterns.
useDeferredValue Config
const SUSPENSE_CONFIG = { timeoutMs: 2000 }; useDeferredValue accepts an optional Suspense Config with a timeoutMs. This timeout (in milliseconds) tells React how long the deferred value is allowed to lag behind. React will always try to use a shorter lag when network and device allows it.

How to Contribute

React is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody on facebook.com. We're still working out the kinks to make contributing to this project as easy and transparent as possible, but we're not quite there yet. Hopefully this document makes the process for contributing clear and answers some questions that you may have.

Code of Conduct

Facebook has adopted the Contributor Covenant as its Code of Conduct, and we expect project participants to adhere to it. Please read the full text so that you can understand what actions will and will not be tolerated.

Open Development

All work on React happens directly on GitHub. Both core team members and external contributors send pull requests which go through the same review process.

Semantic Versioning

React follows semantic versioning. We release patch versions for critical bugfixes, minor versions for new features or non-essential changes, and major versions for any breaking changes. When we make breaking changes, we also introduce deprecation warnings in a minor version so that our users learn about the upcoming changes and migrate their code in advance. Learn more about our commitment to stability and incremental migration in our versioning policy. Every significant change is documented in the changelog file.

Branch Organization

Submit all changes directly to the master branch. We don't use separate branches for development or for upcoming releases. We do our best to keep master in good shape, with all tests passing. Code that lands in master must be compatible with the latest stable release. It may contain additional features, but no breaking changes. We should be able to release a new minor version from the tip of master at any time.

Feature Flags

To keep the master branch in a releasable state, breaking changes and experimental features must be gated behind a feature flag. Feature flags are defined in packages/shared/ReactFeatureFlags.js. Some builds of React may enable different sets of feature flags; for example, the React Native build may be configured differently than React DOM. These flags are found in packages/shared/forks. Feature flags are statically typed by Flow, so you can run yarn flow to confirm that you've updated all the necessary files. React's build system will strip out disabled feature branches before publishing. A continuous integration job runs on every commit to check for changes in bundle size. You can use the change in size as a signal that a feature was gated correctly.

Bugs

Where to Find Known Issues
We are using GitHub Issues for our public bugs. We keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new task, try to make sure your problem doesn't already exist.
Reporting New Issues
The best way to get your bug fixed is to provide a reduced test case. This JSFiddle template is a great starting point.
Security Bugs
Facebook has a bounty program for the safe disclosure of security bugs. With that in mind, please do not file public issues; go through the process outlined on that page.

How to Get in Touch

  • IRC: #reactjs on freenode
  • Discussion forums
There is also an active community of React users on the Discord chat platform in case you need help with React.

Proposing a Change

If you intend to change the public API, or make any non-trivial changes to the implementation, we recommend filing an issue. This lets us reach an agreement on your proposal before you put significant effort into it. If you're only fixing a bug, it's fine to submit a pull request right away but we still recommend to file an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue.

Your First Pull Request

Working on your first Pull Request? You can learn how from this free video series: How to Contribute to an Open Source Project on GitHub To help you get your feet wet and get you familiar with our contribution process, we have a list of good first issues that contain bugs that have a relatively limited scope. This is a great place to get started. If you decide to fix an issue, please be sure to check the comment thread in case somebody is already working on a fix. If nobody is working on it at the moment, please leave a comment stating that you intend to work on it so other people don't accidentally duplicate your effort. If somebody claims an issue but doesn't follow up for more than two weeks, it's fine to take it over but you should still leave a comment.

Sending a Pull Request

The core team is monitoring for pull requests. We will review your pull request and either merge it, request changes to it, or close it with an explanation. For API changes we may need to fix our internal uses at Facebook.com, which could cause some delay. We'll do our best to provide updates and feedback throughout the process. Before submitting a pull request, please make sure the following is done:
  1. Fork the repository and create your branch from master.
  2. Run yarn in the repository root.
  3. If you've fixed a bug or added code that should be tested, add tests!
  4. Ensure the test suite passes (yarn test). Tip: yarn test --watch TestName is helpful in development.
  5. Run yarn test --prod to test in the production environment.
  6. If you need a debugger, run yarn debug-test --watch TestName, open chrome://inspect, and press ¡°Inspect¡±.
  7. Format your code with prettier (yarn prettier).
  8. Make sure your code lints (yarn lint). Tip: yarn linc to only check changed files.
  9. Run the Flow typechecks (yarn flow).
  10. If you haven't already, complete the CLA.

Contributor License Agreement (CLA)

In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username. Complete your CLA here.

Contribution Prerequisites

  • You have Node installed at v8.0.0+ and Yarn at v1.2.0+.
  • You have JDK installed.
  • You have gcc installed or are comfortable installing a compiler if needed. Some of our dependencies may require a compilation step. On OS X, the Xcode Command Line Tools will cover this. On Ubuntu, apt-get install build-essential will install the required packages. Similar commands should work on other Linux distros. Windows will require some additional steps, see the node-gyp installation instructions for details.
  • You are familiar with Git.

Development Workflow

After cloning React, run yarn to fetch its dependencies. Then, you can run several commands:
  • yarn lint checks the code style.
  • yarn linc is like yarn lint but faster because it only checks files that differ in your branch.
  • yarn test runs the complete test suite.
  • yarn test --watch runs an interactive test watcher.
  • yarn test --prod runs tests in the production environment.
  • yarn test <pattern> runs tests with matching filenames.
  • yarn debug-test is just like yarn test but with a debugger. Open chrome://inspect and press ¡°Inspect¡±.
  • yarn flow runs the Flow typechecks.
  • yarn build creates a build folder with all the packages.
  • yarn build react/index,react-dom/index --type=UMD creates UMD builds of just React and ReactDOM.
We recommend running yarn test (or its variations above) to make sure you don't introduce any regressions as you work on your change. However, it can be handy to try your build of React in a real project. First, run yarn build. This will produce pre-built bundles in build folder, as well as prepare npm packages inside build/packages. The easiest way to try your changes is to run yarn build react/index,react-dom/index --type=UMD and then open fixtures/packaging/babel-standalone/dev.html. This file already uses react.development.js from the build folder so it will pick up your changes. If you want to try your changes in your existing React project, you may copy build/dist/react.development.js, build/dist/react-dom.development.js, or any other build products into your app and use them instead of the stable version. If your project uses React from npm, you may delete react and react-dom in its dependencies and use yarn link to point them to your local build folder. Note that instead of --type=UMD you'll want to pass --type=NODE when building. You'll also need to build the scheduler package: cd ~/path_to_your_react_clone/ yarn build react/index,react/jsx,react-dom/index,scheduler --type=NODE cd build/node_modules/react yarn link cd build/node_modules/react-dom yarn link cd ~/path/to/your/project yarn link react react-dom Every time you run yarn build in the React folder, the updated versions will appear in your project's node_modules. You can then rebuild your project to try your changes. If some package is still missing (e.g. maybe you use react-dom/server in your project), you can always do a full build with yarn build. Note that running yarn build without options takes a long time. We still require that your pull request contains unit tests for any new functionality. This way we can ensure that we don't break your code in the future.

Style Guide

We use an automatic code formatter called Prettier. Run yarn prettier after making any changes to the code. Then, our linter will catch most issues that may exist in your code. You can check the status of your code styling by simply running yarn linc. However, there are still some styles that the linter cannot pick up. If you are unsure about something, looking at Airbnb's Style Guide will guide you in the right direction.

Request for Comments (RFC)

Many changes, including bug fixes and documentation improvements can be implemented and reviewed via the normal GitHub pull request workflow. Some changes though are ¡°substantial¡±, and we ask that these be put through a bit of a design process and produce a consensus among the React core team. The ¡°RFC¡± (request for comments) process is intended to provide a consistent and controlled path for new features to enter the project. You can contribute by visiting the rfcs repository.

License

By contributing to React, you agree that your contributions will be licensed under its MIT license.

What Next?

Read the next section to learn how the codebase is organized.

Codebase Overview

This section will give you an overview of the React codebase organization, its conventions, and the implementation. If you want to contribute to React we hope that this guide will help you feel more comfortable making changes. We don't necessarily recommend any of these conventions in React apps. Many of them exist for historical reasons and might change with time.

Top-Level Folders

After cloning the React repository, you will see a few top-level folders in it:
  • packages contains metadata (such as package.json) and the source code (src subdirectory) for all packages in the React repository. If your change is related to the code, the src subdirectory of each package is where you'll spend most of your time.
  • fixtures contains a few small React test applications for contributors.
  • build is the build output of React. It is not in the repository but it will appear in your React clone after you build it for the first time.
The documentation is hosted in a separate repository from React. There are a few other top-level folders but they are mostly used for the tooling and you likely won't ever encounter them when contributing.

Colocated Tests

We don't have a top-level directory for unit tests. Instead, we put them into a directory called __tests__ relative to the files that they test. For example, a test for setInnerHTML.js is located in __tests__/setInnerHTML-test.js right next to it.

Warnings and Invariants

The React codebase uses console.error to display warnings: if (__DEV__) { console.error('Something is wrong.'); } Warnings are only enabled in development. In production, they are completely stripped out. If you need to forbid some code path from executing, use invariant module instead: var invariant = require('invariant'); invariant( 2 + 2 === 4, 'You shall not pass!' ); The invariant is thrown when the invariant condition is false. ¡°Invariant¡± is just a way of saying ¡°this condition always holds true¡±. You can think about it as making an assertion. It is important to keep development and production behavior similar, so invariant throws both in development and in production. The error messages are automatically replaced with error codes in production to avoid negatively affecting the byte size.

Development and Production

You can use __DEV__ pseudo-global variable in the codebase to guard development-only blocks of code. It is inlined during the compile step, and turns into process.env.NODE_ENV !== 'production' checks in the CommonJS builds. For standalone builds, it becomes true in the unminified build, and gets completely stripped out with the if blocks it guards in the minified build. if (__DEV__) { // This code will only run in development. }

Flow

We recently started introducing Flow checks to the codebase. Files marked with the @flow annotation in the license header comment are being typechecked. We accept pull requests adding Flow annotations to existing code. Flow annotations look like this: ReactRef.detachRefs = function( instance: ReactInstance, element: ReactElement | string | number | null | false, ): void { // ... } When possible, new code should use Flow annotations. You can run yarn flow locally to check your code with Flow.

Multiple Packages

React is a monorepo. Its repository contains multiple separate packages so that their changes can be coordinated together, and issues live in one place.

React Core

The ¡°core¡± of React includes all the top-level React APIs, for example:
  • React.createElement()
  • React.Component
  • React.Children
React core only includes the APIs necessary to define components. It does not include the reconciliation algorithm or any platform-specific code. It is used both by React DOM and React Native components. The code for React core is located in packages/react in the source tree. It is available on npm as the react package. The corresponding standalone browser build is called react.js, and it exports a global called React.

Renderers

React was originally created for the DOM but it was later adapted to also support native platforms with React Native. This introduced the concept of ¡°renderers¡± to React internals. Renderers manage how a React tree turns into the underlying platform calls. Renderers are also located in packages/:
  • React DOM Renderer renders React components to the DOM. It implements top-level ReactDOM APIs and is available as react-dom npm package. It can also be used as standalone browser bundle called react-dom.js that exports a ReactDOM global.
  • React Native Renderer renders React components to native views. It is used internally by React Native.
  • React Test Renderer renders React components to JSON trees. It is used by the Snapshot Testing feature of Jest and is available as react-test-renderer npm package.
The only other officially supported renderer is react-art. It used to be in a separate GitHub repository but we moved it into the main source tree for now.
Note: Technically the react-native-renderer is a very thin layer that teaches React to interact with React Native implementation. The real platform-specific code managing the native views lives in the React Native repository together with its components.

Reconcilers

Even vastly different renderers like React DOM and React Native need to share a lot of logic. In particular, the reconciliation algorithm should be as similar as possible so that declarative rendering, custom components, state, lifecycle methods, and refs work consistently across platforms. To solve this, different renderers share some code between them. We call this part of React a ¡°reconciler¡±. When an update such as setState() is scheduled, the reconciler calls render() on components in the tree and mounts, updates, or unmounts them. Reconcilers are not packaged separately because they currently have no public API. Instead, they are exclusively used by renderers such as React DOM and React Native.

Stack Reconciler

The ¡°stack¡± reconciler is the implementation powering React 15 and earlier. We have since stopped using it, but it is documented in detail in the next section.

Fiber Reconciler

The ¡°fiber¡± reconciler is a new effort aiming to resolve the problems inherent in the stack reconciler and fix a few long-standing issues. It has been the default reconciler since React 16. Its main goals are:
  • Ability to split interruptible work in chunks.
  • Ability to prioritize, rebase and reuse work in progress.
  • Ability to yield back and forth between parents and children to support layout in React.
  • Ability to return multiple elements from render().
  • Better support for error boundaries.
You can read more about React Fiber Architecture here and here. While it has shipped with React 16, the async features are not enabled by default yet. Its source code is located in packages/react-reconciler.

Event System

React implements a layer over native events to smooth out cross-browser differences. Its source code is located in packages/react-dom/src/events.

What Next?

Read the next section to learn about the pre-React 16 implementation of reconciler in more detail. We haven't documented the internals of the new reconciler yet.

Implementation Notes

This section is a collection of implementation notes for the stack reconciler. It is very technical and assumes a strong understanding of React public API as well as how it's divided into core, renderers, and the reconciler. If you're not very familiar with the React codebase, read the codebase overview first. It also assumes an understanding of the differences between React components, their instances, and elements. The stack reconciler was used in React 15 and earlier. It is located at src/renderers/shared/stack/reconciler.

Video: Building React from Scratch

Paul O'Shannessy gave a talk about building React from scratch that largely inspired this document. Both this document and his talk are simplifications of the real codebase so you might get a better understanding by getting familiar with both of them.

Overview

The reconciler itself doesn't have a public API. Renderers like React DOM and React Native use it to efficiently update the user interface according to the React components written by the user.

Mounting as a Recursive Process

Let's consider the first time you mount a component: ReactDOM.render(<App />, rootEl); React DOM will pass <App /> along to the reconciler. Remember that <App /> is a React element, that is, a description of what to render. You can think about it as a plain object: console.log(<App />); // { type: App, props: {} } The reconciler will check if App is a class or a function. If App is a function, the reconciler will call App(props) to get the rendered element. If App is a class, the reconciler will instantiate an App with new App(props), call the componentWillMount() lifecycle method, and then will call the render() method to get the rendered element. Either way, the reconciler will learn the element App ¡°rendered to¡±. This process is recursive. App may render to a <Greeting />, Greeting may render to a <Button />, and so on. The reconciler will ¡°drill down¡± through user-defined components recursively as it learns what each component renders to. You can imagine this process as a pseudocode: function isClass(type) { // React.Component subclasses have this flag return ( Boolean(type.prototype) && Boolean(type.prototype.isReactComponent) ); } // This function takes a React element (e.g. <App />) // and returns a DOM or Native node representing the mounted tree. function mount(element) { var type = element.type; var props = element.props; // We will determine the rendered element // by either running the type as function // or creating an instance and calling render(). var renderedElement; if (isClass(type)) { // Component class var publicInstance = new type(props); // Set the props publicInstance.props = props; // Call the lifecycle if necessary if (publicInstance.componentWillMount) { publicInstance.componentWillMount(); } // Get the rendered element by calling render() renderedElement = publicInstance.render(); } else { // Component function renderedElement = type(props); } // This process is recursive because a component may // return an element with a type of another component. return mount(renderedElement); // Note: this implementation is incomplete and recurses infinitely! // It only handles elements like <App /> or <Button />. // It doesn't handle elements like <div /> or <p /> yet. } var rootEl = document.getElementById('root'); var node = mount(<App />); rootEl.appendChild(node);
Note: This really is a pseudo-code. It isn't similar to the real implementation. It will also cause a stack overflow because we haven't discussed when to stop the recursion.
Let's recap a few key ideas in the example above:
  • React elements are plain objects representing the component type (e.g. App) and the props.
  • User-defined components (e.g. App) can be classes or functions but they all ¡°render to¡± elements.
  • ¡°Mounting¡± is a recursive process that creates a DOM or Native tree given the top-level React element (e.g. <App />).

Mounting Host Elements

This process would be useless if we didn't render something to the screen as a result. In addition to user-defined (¡°composite¡±) components, React elements may also represent platform-specific (¡°host¡±) components. For example, Button might return a <div /> from its render method. If element's type property is a string, we are dealing with a host element: console.log(<div />); // { type: 'div', props: {} } There is no user-defined code associated with host elements. When the reconciler encounters a host element, it lets the renderer take care of mounting it. For example, React DOM would create a DOM node. If the host element has children, the reconciler recursively mounts them following the same algorithm as above. It doesn't matter whether children are host (like <div><hr /></div>), composite (like <div><Button /></div>), or both. The DOM nodes produced by the child components will be appended to the parent DOM node, and recursively, the complete DOM structure will be assembled.
Note: The reconciler itself is not tied to the DOM. The exact result of mounting (sometimes called ¡°mount image¡± in the source code) depends on the renderer, and can be a DOM node (React DOM), a string (React DOM Server), or a number representing a native view (React Native).
If we were to extend the code to handle host elements, it would look like this: function isClass(type) { // React.Component subclasses have this flag return ( Boolean(type.prototype) && Boolean(type.prototype.isReactComponent) ); } // This function only handles elements with a composite type. // For example, it handles <App /> and <Button />, but not a <div />. function mountComposite(element) { var type = element.type; var props = element.props; var renderedElement; if (isClass(type)) { // Component class var publicInstance = new type(props); // Set the props publicInstance.props = props; // Call the lifecycle if necessary if (publicInstance.componentWillMount) { publicInstance.componentWillMount(); } renderedElement = publicInstance.render(); } else if (typeof type === 'function') { // Component function renderedElement = type(props); } // This is recursive but we'll eventually reach the bottom of recursion when // the element is host (e.g. <div />) rather than composite (e.g. <App />): return mount(renderedElement); } // This function only handles elements with a host type. // For example, it handles <div /> and <p /> but not an <App />. function mountHost(element) { var type = element.type; var props = element.props; var children = props.children || []; if (!Array.isArray(children)) { children = [children]; } children = children.filter(Boolean); // This block of code shouldn't be in the reconciler. // Different renderers might initialize nodes differently. // For example, React Native would create iOS or Android views. var node = document.createElement(type); Object.keys(props).forEach(propName => { if (propName !== 'children') { node.setAttribute(propName, props[propName]); } }); // Mount the children children.forEach(childElement => { // Children may be host (e.g. <div />) or composite (e.g. <Button />). // We will also mount them recursively: var childNode = mount(childElement); // This line of code is also renderer-specific. // It would be different depending on the renderer: node.appendChild(childNode); }); // Return the DOM node as mount result. // This is where the recursion ends. return node; } function mount(element) { var type = element.type; if (typeof type === 'function') { // User-defined components return mountComposite(element); } else if (typeof type === 'string') { // Platform-specific components return mountHost(element); } } var rootEl = document.getElementById('root'); var node = mount(<App />); rootEl.appendChild(node); This is working but still far from how the reconciler is really implemented. The key missing ingredient is support for updates.

Introducing Internal Instances

The key feature of React is that you can re-render everything, and it won't recreate the DOM or reset the state: ReactDOM.render(<App />, rootEl); // Should reuse the existing DOM: ReactDOM.render(<App />, rootEl); However, our implementation above only knows how to mount the initial tree. It can't perform updates on it because it doesn't store all the necessary information, such as all the publicInstances, or which DOM nodes correspond to which components. The stack reconciler codebase solves this by making the mount() function a method and putting it on a class. There are drawbacks to this approach, and we are going in the opposite direction in the ongoing rewrite of the reconciler. Nevertheless this is how it works now. Instead of separate mountHost and mountComposite functions, we will create two classes: DOMComponent and CompositeComponent. Both classes have a constructor accepting the element, as well as a mount() method returning the mounted node. We will replace a top-level mount() function with a factory that instantiates the correct class: function instantiateComponent(element) { var type = element.type; if (typeof type === 'function') { // User-defined components return new CompositeComponent(element); } else if (typeof type === 'string') { // Platform-specific components return new DOMComponent(element); } } First, let's consider the implementation of CompositeComponent: class CompositeComponent { constructor(element) { this.currentElement = element; this.renderedComponent = null; this.publicInstance = null; } getPublicInstance() { // For composite components, expose the class instance. return this.publicInstance; } mount() { var element = this.currentElement; var type = element.type; var props = element.props; var publicInstance; var renderedElement; if (isClass(type)) { // Component class publicInstance = new type(props); // Set the props publicInstance.props = props; // Call the lifecycle if necessary if (publicInstance.componentWillMount) { publicInstance.componentWillMount(); } renderedElement = publicInstance.render(); } else if (typeof type === 'function') { // Component function publicInstance = null; renderedElement = type(props); } // Save the public instance this.publicInstance = publicInstance; // Instantiate the child internal instance according to the element. // It would be a DOMComponent for <div /> or <p />, // and a CompositeComponent for <App /> or <Button />: var renderedComponent = instantiateComponent(renderedElement); this.renderedComponent = renderedComponent; // Mount the rendered output return renderedComponent.mount(); } } This is not much different from our previous mountComposite() implementation, but now we can save some information, such as this.currentElement, this.renderedComponent, and this.publicInstance, for use during updates. Note that an instance of CompositeComponent is not the same thing as an instance of the user-supplied element.type. CompositeComponent is an implementation detail of our reconciler, and is never exposed to the user. The user-defined class is the one we read from element.type, and CompositeComponent creates an instance of it. To avoid the confusion, we will call instances of CompositeComponent and DOMComponent ¡°internal instances¡±. They exist so we can associate some long-lived data with them. Only the renderer and the reconciler are aware that they exist. In contrast, we call an instance of the user-defined class a ¡°public instance¡±. The public instance is what you see as this in the render() and other methods of your custom components. The mountHost() function, refactored to be a mount() method on DOMComponent class, also looks familiar: class DOMComponent { constructor(element) { this.currentElement = element; this.renderedChildren = []; this.node = null; } getPublicInstance() { // For DOM components, only expose the DOM node. return this.node; } mount() { var element = this.currentElement; var type = element.type; var props = element.props; var children = props.children || []; if (!Array.isArray(children)) { children = [children]; } // Create and save the node var node = document.createElement(type); this.node = node; // Set the attributes Object.keys(props).forEach(propName => { if (propName !== 'children') { node.setAttribute(propName, props[propName]); } }); // Create and save the contained children. // Each of them can be a DOMComponent or a CompositeComponent, // depending on whether the element type is a string or a function. var renderedChildren = children.map(instantiateComponent); this.renderedChildren = renderedChildren; // Collect DOM nodes they return on mount var childNodes = renderedChildren.map(child => child.mount()); childNodes.forEach(childNode => node.appendChild(childNode)); // Return the DOM node as mount result return node; } } The main difference after refactoring from mountHost() is that we now keep this.node and this.renderedChildren associated with the internal DOM component instance. We will also use them for applying non-destructive updates in the future. As a result, each internal instance, composite or host, now points to its child internal instances. To help visualize this, if a function <App> component renders a <Button> class component, and Button class renders a <div>, the internal instance tree would look like this: [object CompositeComponent] { currentElement: <App />, publicInstance: null, renderedComponent: [object CompositeComponent] { currentElement: <Button />, publicInstance: [object Button], renderedComponent: [object DOMComponent] { currentElement: <div />, node: [object HTMLDivElement], renderedChildren: [] } } } In the DOM you would only see the <div>. However the internal instance tree contains both composite and host internal instances. The composite internal instances need to store:
  • The current element.
  • The public instance if element type is a class.
  • The single rendered internal instance. It can be either a DOMComponent or a CompositeComponent.
The host internal instances need to store:
  • The current element.
  • The DOM node.
  • All the child internal instances. Each of them can be either a DOMComponent or a CompositeComponent.
If you're struggling to imagine how an internal instance tree is structured in more complex applications, React DevTools can give you a close approximation, as it highlights host instances with grey, and composite instances with purple: To complete this refactoring, we will introduce a function that mounts a complete tree into a container node, just like ReactDOM.render(). It returns a public instance, also like ReactDOM.render(): function mountTree(element, containerNode) { // Create the top-level internal instance var rootComponent = instantiateComponent(element); // Mount the top-level component into the container var node = rootComponent.mount(); containerNode.appendChild(node); // Return the public instance it provides var publicInstance = rootComponent.getPublicInstance(); return publicInstance; } var rootEl = document.getElementById('root'); mountTree(<App />, rootEl);

Unmounting

Now that we have internal instances that hold onto their children and the DOM nodes, we can implement unmounting. For a composite component, unmounting calls a lifecycle method and recurses. class CompositeComponent { // ... unmount() { // Call the lifecycle method if necessary var publicInstance = this.publicInstance; if (publicInstance) { if (publicInstance.componentWillUnmount) { publicInstance.componentWillUnmount(); } } // Unmount the single rendered component var renderedComponent = this.renderedComponent; renderedComponent.unmount(); } } For DOMComponent, unmounting tells each child to unmount: class DOMComponent { // ... unmount() { // Unmount all the children var renderedChildren = this.renderedChildren; renderedChildren.forEach(child => child.unmount()); } } In practice, unmounting DOM components also removes the event listeners and clears some caches, but we will skip those details. We can now add a new top-level function called unmountTree(containerNode) that is similar to ReactDOM.unmountComponentAtNode(): function unmountTree(containerNode) { // Read the internal instance from a DOM node: // (This doesn't work yet, we will need to change mountTree() to store it.) var node = containerNode.firstChild; var rootComponent = node._internalInstance; // Unmount the tree and clear the container rootComponent.unmount(); containerNode.innerHTML = ''; } In order for this to work, we need to read an internal root instance from a DOM node. We will modify mountTree() to add the _internalInstance property to the root DOM node. We will also teach mountTree() to destroy any existing tree so it can be called multiple times: function mountTree(element, containerNode) { // Destroy any existing tree if (containerNode.firstChild) { unmountTree(containerNode); } // Create the top-level internal instance var rootComponent = instantiateComponent(element); // Mount the top-level component into the container var node = rootComponent.mount(); containerNode.appendChild(node); // Save a reference to the internal instance node._internalInstance = rootComponent; // Return the public instance it provides var publicInstance = rootComponent.getPublicInstance(); return publicInstance; } Now, running unmountTree(), or running mountTree() repeatedly, removes the old tree and runs the componentWillUnmount() lifecycle method on components.

Updating

In the previous section, we implemented unmounting. However React wouldn't be very useful if each prop change unmounted and mounted the whole tree. The goal of the reconciler is to reuse existing instances where possible to preserve the DOM and the state: var rootEl = document.getElementById('root'); mountTree(<App />, rootEl); // Should reuse the existing DOM: mountTree(<App />, rootEl); We will extend our internal instance contract with one more method. In addition to mount() and unmount(), both DOMComponent and CompositeComponent will implement a new method called receive(nextElement): class CompositeComponent { // ... receive(nextElement) { // ... } } class DOMComponent { // ... receive(nextElement) { // ... } } Its job is to do whatever is necessary to bring the component (and any of its children) up to date with the description provided by the nextElement. This is the part that is often described as ¡°virtual DOM diffing¡± although what really happens is that we walk the internal tree recursively and let each internal instance receive an update.

Updating Composite Components

When a composite component receives a new element, we run the componentWillUpdate() lifecycle method. Then we re-render the component with the new props, and get the next rendered element: class CompositeComponent { // ... receive(nextElement) { var prevProps = this.currentElement.props; var publicInstance = this.publicInstance; var prevRenderedComponent = this.renderedComponent; var prevRenderedElement = prevRenderedComponent.currentElement; // Update *own* element this.currentElement = nextElement; var type = nextElement.type; var nextProps = nextElement.props; // Figure out what the next render() output is var nextRenderedElement; if (isClass(type)) { // Component class // Call the lifecycle if necessary if (publicInstance.componentWillUpdate) { publicInstance.componentWillUpdate(nextProps); } // Update the props publicInstance.props = nextProps; // Re-render nextRenderedElement = publicInstance.render(); } else if (typeof type === 'function') { // Component function nextRenderedElement = type(nextProps); } // ... Next, we can look at the rendered element's type. If the type has not changed since the last render, the component below can also be updated in place. For example, if it returned <Button color="red" /> the first time, and <Button color="blue" /> the second time, we can just tell the corresponding internal instance to receive() the next element: // ... // If the rendered element type has not changed, // reuse the existing component instance and exit. if (prevRenderedElement.type === nextRenderedElement.type) { prevRenderedComponent.receive(nextRenderedElement); return; } // ... However, if the next rendered element has a different type than the previously rendered element, we can't update the internal instance. A <button> can't ¡°become¡± an <input>. Instead, we have to unmount the existing internal instance and mount the new one corresponding to the rendered element type. For example, this is what happens when a component that previously rendered a <button /> renders an <input />: // ... // If we reached this point, we need to unmount the previously // mounted component, mount the new one, and swap their nodes. // Find the old node because it will need to be replaced var prevNode = prevRenderedComponent.getHostNode(); // Unmount the old child and mount a new child prevRenderedComponent.unmount(); var nextRenderedComponent = instantiateComponent(nextRenderedElement); var nextNode = nextRenderedComponent.mount(); // Replace the reference to the child this.renderedComponent = nextRenderedComponent; // Replace the old node with the new one // Note: this is renderer-specific code and // ideally should live outside of CompositeComponent: prevNode.parentNode.replaceChild(nextNode, prevNode); } } To sum this up, when a composite component receives a new element, it may either delegate the update to its rendered internal instance, or unmount it and mount a new one in its place. There is another condition under which a component will re-mount rather than receive an element, and that is when the element's key has changed. We don't discuss key handling in this document because it adds more complexity to an already complex tutorial. Note that we needed to add a method called getHostNode() to the internal instance contract so that it's possible to locate the platform-specific node and replace it during the update. Its implementation is straightforward for both classes: class CompositeComponent { // ... getHostNode() { // Ask the rendered component to provide it. // This will recursively drill down any composites. return this.renderedComponent.getHostNode(); } } class DOMComponent { // ... getHostNode() { return this.node; } }

Updating Host Components

Host component implementations, such as DOMComponent, update differently. When they receive an element, they need to update the underlying platform-specific view. In case of React DOM, this means updating the DOM attributes: class DOMComponent { // ... receive(nextElement) { var node = this.node; var prevElement = this.currentElement; var prevProps = prevElement.props; var nextProps = nextElement.props; this.currentElement = nextElement; // Remove old attributes. Object.keys(prevProps).forEach(propName => { if (propName !== 'children' && !nextProps.hasOwnProperty(propName)) { node.removeAttribute(propName); } }); // Set next attributes. Object.keys(nextProps).forEach(propName => { if (propName !== 'children') { node.setAttribute(propName, nextProps[propName]); } }); // ... Then, host components need to update their children. Unlike composite components, they might contain more than a single child. In this simplified example, we use an array of internal instances and iterate over it, either updating or replacing the internal instances depending on whether the received type matches their previous type. The real reconciler also takes element's key in the account and track moves in addition to insertions and deletions, but we will omit this logic. We collect DOM operations on children in a list so we can execute them in batch: // ... // These are arrays of React elements: var prevChildren = prevProps.children || []; if (!Array.isArray(prevChildren)) { prevChildren = [prevChildren]; } var nextChildren = nextProps.children || []; if (!Array.isArray(nextChildren)) { nextChildren = [nextChildren]; } // These are arrays of internal instances: var prevRenderedChildren = this.renderedChildren; var nextRenderedChildren = []; // As we iterate over children, we will add operations to the array. var operationQueue = []; // Note: the section below is extremely simplified! // It doesn't handle reorders, children with holes, or keys. // It only exists to illustrate the overall flow, not the specifics. for (var i = 0; i < nextChildren.length; i++) { // Try to get an existing internal instance for this child var prevChild = prevRenderedChildren[i]; // If there is no internal instance under this index, // a child has been appended to the end. Create a new // internal instance, mount it, and use its node. if (!prevChild) { var nextChild = instantiateComponent(nextChildren[i]); var node = nextChild.mount(); // Record that we need to append a node operationQueue.push({type: 'ADD', node}); nextRenderedChildren.push(nextChild); continue; } // We can only update the instance if its element's type matches. // For example, <Button size="small" /> can be updated to // <Button size="large" /> but not to an <App />. var canUpdate = prevChildren[i].type === nextChildren[i].type; // If we can't update an existing instance, we have to unmount it // and mount a new one instead of it. if (!canUpdate) { var prevNode = prevChild.getHostNode(); prevChild.unmount(); var nextChild = instantiateComponent(nextChildren[i]); var nextNode = nextChild.mount(); // Record that we need to swap the nodes operationQueue.push({type: 'REPLACE', prevNode, nextNode}); nextRenderedChildren.push(nextChild); continue; } // If we can update an existing internal instance, // just let it receive the next element and handle its own update. prevChild.receive(nextChildren[i]); nextRenderedChildren.push(prevChild); } // Finally, unmount any children that don't exist: for (var j = nextChildren.length; j < prevChildren.length; j++) { var prevChild = prevRenderedChildren[j]; var node = prevChild.getHostNode(); prevChild.unmount(); // Record that we need to remove the node operationQueue.push({type: 'REMOVE', node}); } // Point the list of rendered children to the updated version. this.renderedChildren = nextRenderedChildren; // ... As the last step, we execute the DOM operations. Again, the real reconciler code is more complex because it also handles moves: // ... // Process the operation queue. while (operationQueue.length > 0) { var operation = operationQueue.shift(); switch (operation.type) { case 'ADD': this.node.appendChild(operation.node); break; case 'REPLACE': this.node.replaceChild(operation.nextNode, operation.prevNode); break; case 'REMOVE': this.node.removeChild(operation.node); break; } } } } And that is it for updating host components.

Top-Level Updates

Now that both CompositeComponent and DOMComponent implement the receive(nextElement) method, we can change the top-level mountTree() function to use it when the element type is the same as it was the last time: function mountTree(element, containerNode) { // Check for an existing tree if (containerNode.firstChild) { var prevNode = containerNode.firstChild; var prevRootComponent = prevNode._internalInstance; var prevElement = prevRootComponent.currentElement; // If we can, reuse the existing root component if (prevElement.type === element.type) { prevRootComponent.receive(element); return; } // Otherwise, unmount the existing tree unmountTree(containerNode); } // ... } Now calling mountTree() two times with the same type isn't destructive: var rootEl = document.getElementById('root'); mountTree(<App />, rootEl); // Reuses the existing DOM: mountTree(<App />, rootEl); These are the basics of how React works internally.

What We Left Out

This document is simplified compared to the real codebase. There are a few important aspects we didn't address:
  • Components can render null, and the reconciler can handle ¡°empty slots¡± in arrays and rendered output.
  • The reconciler also reads key from the elements, and uses it to establish which internal instance corresponds to which element in an array. A bulk of complexity in the actual React implementation is related to that.
  • In addition to composite and host internal instance classes, there are also classes for ¡°text¡± and ¡°empty¡± components. They represent text nodes and the ¡°empty slots¡± you get by rendering null.
  • Renderers use injection to pass the host internal class to the reconciler. For example, React DOM tells the reconciler to use ReactDOMComponent as the host internal instance implementation.
  • The logic for updating the list of children is extracted into a mixin called ReactMultiChild which is used by the host internal instance class implementations both in React DOM and React Native.
  • The reconciler also implements support for setState() in composite components. Multiple updates inside event handlers get batched into a single update.
  • The reconciler also takes care of attaching and detaching refs to composite components and host nodes.
  • Lifecycle methods that are called after the DOM is ready, such as componentDidMount() and componentDidUpdate(), get collected into ¡°callback queues¡± and are executed in a single batch.
  • React puts information about the current update into an internal object called ¡°transaction¡±. Transactions are useful for keeping track of the queue of pending lifecycle methods, the current DOM nesting for the warnings, and anything else that is ¡°global¡± to a specific update. Transactions also ensure React ¡°cleans everything up¡± after updates. For example, the transaction class provided by React DOM restores the input selection after any update.

Jumping into the Code

  • ReactMount is where the code like mountTree() and unmountTree() from this tutorial lives. It takes care of mounting and unmounting top-level components. ReactNativeMount is its React Native analog.
  • ReactDOMComponent is the equivalent of DOMComponent in this tutorial. It implements the host component class for React DOM renderer. ReactNativeBaseComponent is its React Native analog.
  • ReactCompositeComponent is the equivalent of CompositeComponent in this tutorial. It handles calling user-defined components and maintaining their state.
  • instantiateReactComponent contains the switch that picks the right internal instance class to construct for an element. It is equivalent to instantiateComponent() in this tutorial.
  • ReactReconciler is a wrapper with mountComponent(), receiveComponent(), and unmountComponent() methods. It calls the underlying implementations on the internal instances, but also includes some code around them that is shared by all internal instance implementations.
  • ReactChildReconciler implements the logic for mounting, updating, and unmounting children according to the key of their elements.
  • ReactMultiChild implements processing the operation queue for child insertions, deletions, and moves independently of the renderer.
  • mount(), receive(), and unmount() are really called mountComponent(), receiveComponent(), and unmountComponent() in React codebase for legacy reasons, but they receive elements.
  • Properties on the internal instances start with an underscore, e.g. _currentElement. They are considered to be read-only public fields throughout the codebase.

Future Directions

Stack reconciler has inherent limitations such as being synchronous and unable to interrupt the work or split it in chunks. There is a work in progress on the new Fiber reconciler with a completely different architecture. In the future, we intend to replace stack reconciler with it, but at the moment it is far from feature parity.

Next Steps

Read the next section to learn about the guiding principles we use for React development.

Design Principles

We wrote this document so that you have a better idea of how we decide what React does and what React doesn't do, and what our development philosophy is like. While we are excited to see community contributions, we are not likely to choose a path that violates one or more of these principles.
Note: This document assumes a strong understanding of React. It describes the design principles of React itself, not React components or applications. For an introduction to React, check out Thinking in React instead.

Composition

The key feature of React is composition of components. Components written by different people should work well together. It is important to us that you can add functionality to a component without causing rippling changes throughout the codebase. For example, it should be possible to introduce some local state into a component without changing any of the components using it. Similarly, it should be possible to add some initialization and teardown code to any component when necessary. There is nothing ¡°bad¡± about using state or lifecycle methods in components. Like any powerful feature, they should be used in moderation, but we have no intention to remove them. On the contrary, we think they are integral parts of what makes React useful. We might enable more functional patterns in the future, but both local state and lifecycle methods will be a part of that model. Components are often described as ¡°just functions¡± but in our view they need to be more than that to be useful. In React, components describe any composable behavior, and this includes rendering, lifecycle, and state. Some external libraries like Relay augment components with other responsibilities such as describing data dependencies. It is possible that those ideas might make it back into React too in some form.

Common Abstraction

In general we resist adding features that can be implemented in userland. We don't want to bloat your apps with useless library code. However, there are exceptions to this. For example, if React didn't provide support for local state or lifecycle methods, people would create custom abstractions for them. When there are multiple abstractions competing, React can't enforce or take advantage of the properties of either of them. It has to work with the lowest common denominator. This is why sometimes we add features to React itself. If we notice that many components implement a certain feature in incompatible or inefficient ways, we might prefer to bake it into React. We don't do it lightly. When we do it, it's because we are confident that raising the abstraction level benefits the whole ecosystem. State, lifecycle methods, cross-browser event normalization are good examples of this. We always discuss such improvement proposals with the community. You can find some of those discussions by the ¡°big picture¡± label on the React issue tracker.

Escape Hatches

React is pragmatic. It is driven by the needs of the products written at Facebook. While it is influenced by some paradigms that are not yet fully mainstream such as functional programming, staying accessible to a wide range of developers with different skills and experience levels is an explicit goal of the project. If we want to deprecate a pattern that we don't like, it is our responsibility to consider all existing use cases for it and educate the community about the alternatives before we deprecate it. If some pattern that is useful for building apps is hard to express in a declarative way, we will provide an imperative API for it. If we can't figure out a perfect API for something that we found necessary in many apps, we will provide a temporary subpar working API as long as it is possible to get rid of it later and it leaves the door open for future improvements.

Stability

We value API stability. At Facebook, we have more than 50 thousand components using React. Many other companies, including Twitter and Airbnb, are also heavy users of React. This is why we are usually reluctant to change public APIs or behavior. However we think stability in the sense of ¡°nothing changes¡± is overrated. It quickly turns into stagnation. Instead, we prefer the stability in the sense of ¡°It is heavily used in production, and when something changes, there is a clear (and preferably automated) migration path.¡± When we deprecate a pattern, we study its internal usage at Facebook and add deprecation warnings. They let us assess the impact of the change. Sometimes we back out if we see that it is too early, and we need to think more strategically about getting the codebases to the point where they are ready for this change. If we are confident that the change is not too disruptive and the migration strategy is viable for all use cases, we release the deprecation warning to the open source community. We are closely in touch with many users of React outside of Facebook, and we monitor popular open source projects and guide them in fixing those deprecations. Given the sheer size of the Facebook React codebase, successful internal migration is often a good indicator that other companies won't have problems either. Nevertheless sometimes people point out additional use cases we haven't thought of, and we add escape hatches for them or rethink our approach. We don't deprecate anything without a good reason. We recognize that sometimes deprecations warnings cause frustration but we add them because deprecations clean up the road for the improvements and new features that we and many people in the community consider valuable. For example, we added a warning about unknown DOM props in React 15.2.0. Many projects were affected by this. However fixing this warning is important so that we can introduce the support for custom attributes to React. There is a reason like this behind every deprecation that we add. When we add a deprecation warning, we keep it for the rest of the current major version, and change the behavior in the next major version. If there is a lot of repetitive manual work involved, we release a codemod script that automates most of the change. Codemods enable us to move forward without stagnation in a massive codebase, and we encourage you to use them as well. You can find the codemods that we released in the react-codemod repository.

Interoperability

We place high value in interoperability with existing systems and gradual adoption. Facebook has a massive non-React codebase. Its website uses a mix of a server-side component system called XHP, internal UI libraries that came before React, and React itself. It is important to us that any product team can start using React for a small feature rather than rewrite their code to bet on it. This is why React provides escape hatches to work with mutable models, and tries to work well together with other UI libraries. You can wrap an existing imperative UI into a declarative component, and vice versa. This is crucial for gradual adoption.

Scheduling

Even when your components are described as functions, when you use React you don't call them directly. Every component returns a description of what needs to be rendered, and that description may include both user-written components like <LikeButton> and platform-specific components like <div>. It is up to React to ¡°unroll¡± <LikeButton> at some point in the future and actually apply changes to the UI tree according to the render results of the components recursively. This is a subtle distinction but a powerful one. Since you don't call that component function but let React call it, it means React has the power to delay calling it if necessary. In its current implementation React walks the tree recursively and calls render functions of the whole updated tree during a single tick. However in the future it might start delaying some updates to avoid dropping frames. This is a common theme in React design. Some popular libraries implement the ¡°push¡± approach where computations are performed when the new data is available. React, however, sticks to the ¡°pull¡± approach where computations can be delayed until necessary. React is not a generic data processing library. It is a library for building user interfaces. We think that it is uniquely positioned in an app to know which computations are relevant right now and which are not. If something is offscreen, we can delay any logic related to it. If data is arriving faster than the frame rate, we can coalesce and batch updates. We can prioritize work coming from user interactions (such as an animation caused by a button click) over less important background work (such as rendering new content just loaded from the network) to avoid dropping frames. To be clear, we are not taking advantage of this right now. However the freedom to do something like this is why we prefer to have control over scheduling, and why setState() is asynchronous. Conceptually, we think of it as ¡°scheduling an update¡±. The control over scheduling would be harder for us to gain if we let the user directly compose views with a ¡°push¡± based paradigm common in some variations of Functional Reactive Programming. We want to own the ¡°glue¡± code. It is a key goal for React that the amount of the user code that executes before yielding back into React is minimal. This ensures that React retains the capability to schedule and split work in chunks according to what it knows about the UI. There is an internal joke in the team that React should have been called ¡°Schedule¡± because React does not want to be fully ¡°reactive¡±.

Developer Experience

Providing a good developer experience is important to us. For example, we maintain React DevTools which let you inspect the React component tree in Chrome and Firefox. We have heard that it brings a big productivity boost both to the Facebook engineers and to the community. We also try to go an extra mile to provide helpful developer warnings. For example, React warns you in development if you nest tags in a way that the browser doesn't understand, or if you make a common typo in the API. Developer warnings and the related checks are the main reason why the development version of React is slower than the production version. The usage patterns that we see internally at Facebook help us understand what the common mistakes are, and how to prevent them early. When we add new features, we try to anticipate the common mistakes and warn about them. We are always looking out for ways to improve the developer experience. We love to hear your suggestions and accept your contributions to make it even better.

Debugging

When something goes wrong, it is important that you have breadcrumbs to trace the mistake to its source in the codebase. In React, props and state are those breadcrumbs. If you see something wrong on the screen, you can open React DevTools, find the component responsible for rendering, and then see if the props and state are correct. If they are, you know that the problem is in the component's render() function, or some function that is called by render(). The problem is isolated. If the state is wrong, you know that the problem is caused by one of the setState() calls in this file. This, too, is relatively simple to locate and fix because usually there are only a few setState() calls in a single file. If the props are wrong, you can traverse the tree up in the inspector, looking for the component that first ¡°poisoned the well¡± by passing bad props down. This ability to trace any UI to the data that produced it in the form of current props and state is very important to React. It is an explicit design goal that state is not ¡°trapped¡± in closures and combinators, and is available to React directly. While the UI is dynamic, we believe that synchronous render() functions of props and state turn debugging from guesswork into a boring but finite procedure. We would like to preserve this constraint in React even though it makes some use cases, like complex animations, harder.

Configuration

We find global runtime configuration options to be problematic. For example, it is occasionally requested that we implement a function like React.configure(options) or React.register(component). However this poses multiple problems, and we are not aware of good solutions to them. What if somebody calls such a function from a third-party component library? What if one React app embeds another React app, and their desired configurations are incompatible? How can a third-party component specify that it requires a particular configuration? We think that global configuration doesn't work well with composition. Since composition is central to React, we don't provide global configuration in code. We do, however, provide some global configuration on the build level. For example, we provide separate development and production builds. We may also add a profiling build in the future, and we are open to considering other build flags.

Beyond the DOM

We see the value of React in the way it allows us to write components that have fewer bugs and compose together well. DOM is the original rendering target for React but React Native is just as important both to Facebook and the community. Being renderer-agnostic is an important design constraint of React. It adds some overhead in the internal representations. On the other hand, any improvements to the core translate across platforms. Having a single programming model lets us form engineering teams around products instead of platforms. So far the tradeoff has been worth it for us.

Implementation

We try to provide elegant APIs where possible. We are much less concerned with the implementation being elegant. The real world is far from perfect, and to a reasonable extent we prefer to put the ugly code into the library if it means the user does not have to write it. When we evaluate new code, we are looking for an implementation that is correct, performant and affords a good developer experience. Elegance is secondary. We prefer boring code to clever code. Code is disposable and often changes. So it is important that it doesn't introduce new internal abstractions unless absolutely necessary. Verbose code that is easy to move around, change and remove is preferred to elegant code that is prematurely abstracted and hard to change.

Optimized for Tooling

Some commonly used APIs have verbose names. For example, we use componentDidMount() instead of didMount() or onMount(). This is intentional. The goal is to make the points of interaction with the library highly visible. In a massive codebase like Facebook, being able to search for uses of specific APIs is very important. We value distinct verbose names, and especially for the features that should be used sparingly. For example, dangerouslySetInnerHTML is hard to miss in a code review. Optimizing for search is also important because of our reliance on codemods to make breaking changes. We want it to be easy and safe to apply vast automated changes across the codebase, and unique verbose names help us achieve this. Similarly, distinctive names make it easy to write custom lint rules about using React without worrying about potential false positives. JSX plays a similar role. While it is not required with React, we use it extensively at Facebook both for aesthetic and pragmatic reasons. In our codebase, JSX provides an unambiguous hint to the tools that they are dealing with a React element tree. This makes it possible to add build-time optimizations such as hoisting constant elements, safely lint and codemod internal component usage, and include JSX source location into the warnings.

Dogfooding

We try our best to address the problems raised by the community. However we are likely to prioritize the issues that people are also experiencing internally at Facebook. Perhaps counter-intuitively, we think this is the main reason why the community can bet on React. Heavy internal usage gives us the confidence that React won't disappear tomorrow. React was created at Facebook to solve its problems. It brings tangible business value to the company and is used in many of its products. Dogfooding it means that our vision stays sharp and we have a focused direction going forward. This doesn't mean that we ignore the issues raised by the community. For example, we added support for web components and SVG to React even though we don't rely on either of them internally. We are actively listening to your pain points and address them to the best of our ability. The community is what makes React special to us, and we are honored to contribute back. After releasing many open source projects at Facebook, we have learned that trying to make everyone happy at the same time produced projects with poor focus that didn't grow well. Instead, we found that picking a small audience and focusing on making them happy brings a positive net effect. That's exactly what we did with React, and so far solving the problems encountered by Facebook product teams has translated well to the open source community. The downside of this approach is that sometimes we fail to give enough focus to the things that Facebook teams don't have to deal with, such as the ¡°getting started¡± experience. We are acutely aware of this, and we are thinking of how to improve in a way that would benefit everyone in the community without making the same mistakes we did with open source projects before.

AJAX and APIs

How can I make an AJAX call?

You can use any AJAX library you like with React. Some popular ones are Axios, jQuery AJAX, and the browser built-in window.fetch.

Where in the component lifecycle should I make an AJAX call?

You should populate data with AJAX calls in the componentDidMount lifecycle method. This is so you can use setState to update your component when the data is retrieved.

Example: Using AJAX results to set local state

The component below demonstrates how to make an AJAX call in componentDidMount to populate local component state. The example API returns a JSON object like this: { "items": [ { "id": 1, "name": "Apples", "price": "$2" }, { "id": 2, "name": "Peaches", "price": "$5" } ] } class MyComponent extends React.Component { constructor(props) { super(props); this.state = { error: null, isLoaded: false, items: [] }; } componentDidMount() { fetch("https://api.example.com/items") .then(res => res.json()) .then( (result) => { this.setState({ isLoaded: true, items: result.items }); }, // Note: it's important to handle errors here // instead of a catch() block so that we don't swallow // exceptions from actual bugs in components. (error) => { this.setState({ isLoaded: true, error }); } ) } render() { const { error, isLoaded, items } = this.state; if (error) { return <div>Error: {error.message}</div>; } else if (!isLoaded) { return <div>Loading...</div>; } else { return ( <ul> {items.map(item => ( <li key={item.id}> {item.name} {item.price} </li> ))} </ul> ); } } } Here is the equivalent with Hooks: function MyComponent() { const [error, setError] = useState(null); const [isLoaded, setIsLoaded] = useState(false); const [items, setItems] = useState([]); // Note: the empty deps array [] means // this useEffect will run once // similar to componentDidMount() useEffect(() => { fetch("https://api.example.com/items") .then(res => res.json()) .then( (result) => { setIsLoaded(true); setItems(result); }, // Note: it's important to handle errors here // instead of a catch() block so that we don't swallow // exceptions from actual bugs in components. (error) => { setIsLoaded(true); setError(error); } ) }, []) if (error) { return <div>Error: {error.message}</div>; } else if (!isLoaded) { return <div>Loading...</div>; } else { return ( <ul> {items.map(item => ( <li key={item.id}> {item.name} {item.price} </li> ))} </ul> ); } }

Babel, JSX, and Build Steps

Do I need to use JSX with React?

No! Check out ¡°React Without JSX¡± to learn more.

Do I need to use ES6 (+) with React?

No! Check out ¡°React Without ES6¡± to learn more.

How can I write comments in JSX?

<div> {/* Comment goes here */} Hello, {name}! </div> <div> {/* It also works for multi-line comments. */} Hello, {name}! </div>

Passing Functions to Components

How do I pass an event handler (like onClick) to a component?

Pass event handlers and other functions as props to child components: <button onClick={this.handleClick}> If you need to have access to the parent component in the handler, you also need to bind the function to the component instance (see below).

How do I bind a function to a component instance?

There are several ways to make sure functions have access to component attributes like this.props and this.state, depending on which syntax and build steps you are using.
Bind in Constructor (ES2015)
class Foo extends Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick() { console.log('Click happened'); } render() { return <button onClick={this.handleClick}>Click Me</button>; } }
Class Properties (Stage 3 Proposal)
class Foo extends Component { // Note: this syntax is experimental and not standardized yet. handleClick = () => { console.log('Click happened'); } render() { return <button onClick={this.handleClick}>Click Me</button>; } }
Bind in Render
class Foo extends Component { handleClick() { console.log('Click happened'); } render() { return <button onClick={this.handleClick.bind(this)}>Click Me</button>; } }
Note: Using Function.prototype.bind in render creates a new function each time the component renders, which may have performance implications (see below).
Arrow Function in Render
class Foo extends Component { handleClick() { console.log('Click happened'); } render() { return <button onClick={() => this.handleClick()}>Click Me</button>; } }
Note: Using an arrow function in render creates a new function each time the component renders, which may break optimizations based on strict identity comparison.

Is it OK to use arrow functions in render methods?

Generally speaking, yes, it is OK, and it is often the easiest way to pass parameters to callback functions. If you do have performance issues, by all means, optimize!

Why is binding necessary at all?

In JavaScript, these two code snippets are not equivalent: obj.method(); var method = obj.method; method(); Binding methods helps ensure that the second snippet works the same way as the first one. With React, typically you only need to bind the methods you pass to other components. For example, <button onClick={this.handleClick}> passes this.handleClick so you want to bind it. However, it is unnecessary to bind the render method or the lifecycle methods: we don't pass them to other components. This post by Yehuda Katz explains what binding is, and how functions work in JavaScript, in detail.

Why is my function being called every time the component renders?

Make sure you aren't calling the function when you pass it to the component: render() { // Wrong: handleClick is called instead of passed as a reference! return <button onClick={this.handleClick()}>Click Me</button> } Instead, pass the function itself (without parens): render() { // Correct: handleClick is passed as a reference! return <button onClick={this.handleClick}>Click Me</button> }

How do I pass a parameter to an event handler or callback?

You can use an arrow function to wrap around an event handler and pass parameters: <button onClick={() => this.handleClick(id)} /> This is equivalent to calling .bind: <button onClick={this.handleClick.bind(this, id)} />
Example: Passing params using arrow functions
const A = 65 // ASCII character code class Alphabet extends React.Component { constructor(props) { super(props); this.state = { justClicked: null, letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i)) }; } handleClick(letter) { this.setState({ justClicked: letter }); } render() { return ( <div> Just clicked: {this.state.justClicked} <ul> {this.state.letters.map(letter => <li key={letter} onClick={() => this.handleClick(letter)}> {letter} </li> )} </ul> </div> ) } }
Example: Passing params using data-attributes
Alternately, you can use DOM APIs to store data needed for event handlers. Consider this approach if you need to optimize a large number of elements or have a render tree that relies on React.PureComponent equality checks. const A = 65 // ASCII character code class Alphabet extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); this.state = { justClicked: null, letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i)) }; } handleClick(e) { this.setState({ justClicked: e.target.dataset.letter }); } render() { return ( <div> Just clicked: {this.state.justClicked} <ul> {this.state.letters.map(letter => <li key={letter} data-letter={letter} onClick={this.handleClick}> {letter} </li> )} </ul> </div> ) } }

How can I prevent a function from being called too quickly or too many times in a row?

If you have an event handler such as onClick or onScroll and want to prevent the callback from being fired too quickly, then you can limit the rate at which callback is executed. This can be done by using:
  • throttling: sample changes based on a time based frequency (eg _.throttle)
  • debouncing: publish changes after a period of inactivity (eg _.debounce)
  • requestAnimationFrame throttling: sample changes based on requestAnimationFrame (eg raf-schd)
See this visualization for a comparison of throttle and debounce functions.
Note: _.debounce, _.throttle and raf-schd provide a cancel method to cancel delayed callbacks. You should either call this method from componentWillUnmount or check to ensure that the component is still mounted within the delayed function.
Throttle
Throttling prevents a function from being called more than once in a given window of time. The example below throttles a ¡°click¡± handler to prevent calling it more than once per second. import throttle from 'lodash.throttle'; class LoadMoreButton extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); this.handleClickThrottled = throttle(this.handleClick, 1000); } componentWillUnmount() { this.handleClickThrottled.cancel(); } render() { return <button onClick={this.handleClickThrottled}>Load More</button>; } handleClick() { this.props.loadMore(); } }
Debounce
Debouncing ensures that a function will not be executed until after a certain amount of time has passed since it was last called. This can be useful when you have to perform some expensive calculation in response to an event that might dispatch rapidly (eg scroll or keyboard events). The example below debounces text input with a 250ms delay. import debounce from 'lodash.debounce'; class Searchbox extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.emitChangeDebounced = debounce(this.emitChange, 250); } componentWillUnmount() { this.emitChangeDebounced.cancel(); } render() { return ( <input type="text" onChange={this.handleChange} placeholder="Search..." defaultValue={this.props.value} /> ); } handleChange(e) { this.emitChangeDebounced(e.target.value); } emitChange(value) { this.props.onChange(value); } }
requestAnimationFrame throttling
requestAnimationFrame is a way of queuing a function to be executed in the browser at the optimal time for rendering performance. A function that is queued with requestAnimationFrame will fire in the next frame. The browser will work hard to ensure that there are 60 frames per second (60 fps). However, if the browser is unable to it will naturally limit the amount of frames in a second. For example, a device might only be able to handle 30 fps and so you will only get 30 frames in that second. Using requestAnimationFrame for throttling is a useful technique in that it prevents you from doing more than 60 updates in a second. If you are doing 100 updates in a second this creates additional work for the browser that the user will not see anyway.
Note: Using this technique will only capture the last published value in a frame. You can see an example of how this optimization works on MDN
import rafSchedule from 'raf-schd'; class ScrollListener extends React.Component { constructor(props) { super(props); this.handleScroll = this.handleScroll.bind(this); // Create a new function to schedule updates. this.scheduleUpdate = rafSchedule( point => this.props.onScroll(point) ); } handleScroll(e) { // When we receive a scroll event, schedule an update. // If we receive many updates within a frame, we'll only publish the latest value. this.scheduleUpdate({ x: e.clientX, y: e.clientY }); } componentWillUnmount() { // Cancel any pending updates since we're unmounting. this.scheduleUpdate.cancel(); } render() { return ( <div style={{ overflow: 'scroll' }} onScroll={this.handleScroll} > <img src="/my-huge-image.jpg" /> </div> ); } }
Testing your rate limiting
When testing your rate limiting code works correctly it is helpful to have the ability to fast forward time. If you are using jest then you can use mock timers to fast forward time. If you are using requestAnimationFrame throttling then you may find raf-stub to be a useful tool to control the ticking of animation frames.

Component State

What does setState do?

setState() schedules an update to a component's state object. When state changes, the component responds by re-rendering.

What is the difference between state and props?

props (short for ¡°properties¡±) and state are both plain JavaScript objects. While both hold information that influences the output of render, they are different in one important way: props get passed to the component (similar to function parameters) whereas state is managed within the component (similar to variables declared within a function). Here are some good resources for further reading on when to use props vs state:
  • Props vs State
  • ReactJS: Props vs. State

Why is setState giving me the wrong value?

In React, both this.props and this.state represent the rendered values, i.e. what's currently on the screen. Calls to setState are asynchronous - don't rely on this.state to reflect the new value immediately after calling setState. Pass an updater function instead of an object if you need to compute values based on the current state (see below for details). Example of code that will not behave as expected: incrementCount() { // Note: this will *not* work as intended. this.setState({count: this.state.count + 1}); } handleSomething() { // Let's say `this.state.count` starts at 0. this.incrementCount(); this.incrementCount(); this.incrementCount(); // When React re-renders the component, `this.state.count` will be 1, but you expected 3. // This is because `incrementCount()` function above reads from `this.state.count`, // but React doesn't update `this.state.count` until the component is re-rendered. // So `incrementCount()` ends up reading `this.state.count` as 0 every time, and sets it to 1. // The fix is described below! } See below for how to fix this problem.

How do I update state with values that depend on the current state?

Pass a function instead of an object to setState to ensure the call always uses the most updated version of state (see below).

What is the difference between passing an object or a function in setState?

Passing an update function allows you to access the current state value inside the updater. Since setState calls are batched, this lets you chain updates and ensure they build on top of each other instead of conflicting: incrementCount() { this.setState((state) => { // Important: read `state` instead of `this.state` when updating. return {count: state.count + 1} }); } handleSomething() { // Let's say `this.state.count` starts at 0. this.incrementCount(); this.incrementCount(); this.incrementCount(); // If you read `this.state.count` now, it would still be 0. // But when React re-renders the component, it will be 3. } Learn more about setState

When is setState asynchronous?

Currently, setState is asynchronous inside event handlers. This ensures, for example, that if both Parent and Child call setState during a click event, Child isn't re-rendered twice. Instead, React ¡°flushes¡± the state updates at the end of the browser event. This results in significant performance improvements in larger apps. This is an implementation detail so avoid relying on it directly. In the future versions, React will batch updates by default in more cases.

Why doesn't React update this.state synchronously?

As explained in the previous section, React intentionally ¡°waits¡± until all components call setState() in their event handlers before starting to re-render. This boosts performance by avoiding unnecessary re-renders. However, you might still be wondering why React doesn't just update this.state immediately without re-rendering. There are two main reasons:
  • This would break the consistency between props and state, causing issues that are very hard to debug.
  • This would make some of the new features we're working on impossible to implement.
This GitHub comment dives deep into the specific examples.

Should I use a state management library like Redux or MobX?

Maybe. It's a good idea to get to know React first, before adding in additional libraries. You can build quite complex applications using only React.

Styling and CSS

How do I add CSS classes to components?

Pass a string as the className prop: render() { return <span className="menu navigation-menu">Menu</span> } It is common for CSS classes to depend on the component props or state: render() { let className = 'menu'; if (this.props.isActive) { className += ' menu-active'; } return <span className={className}>Menu</span> }
Tip If you often find yourself writing code like this, classnames package can simplify it.

Can I use inline styles?

Yes, see the docs on styling here.

Are inline styles bad?

CSS classes are generally better for performance than inline styles.

What is CSS-in-JS?

¡°CSS-in-JS¡± refers to a pattern where CSS is composed using JavaScript instead of defined in external files. Note that this functionality is not a part of React, but provided by third-party libraries. React does not have an opinion about how styles are defined; if in doubt, a good starting point is to define your styles in a separate *.css file as usual and refer to them using className.

Can I do animations in React?

React can be used to power animations. See React Transition Group and React Motion or React Spring, for example.

File Structure

Is there a recommended way to structure React projects?

React doesn't have opinions on how you put files into folders. That said there are a few common approaches popular in the ecosystem you may want to consider.
Grouping by features or routes
One common way to structure projects is to locate CSS, JS, and tests together inside folders grouped by feature or route. common/ Avatar.js Avatar.css APIUtils.js APIUtils.test.js feed/ index.js Feed.js Feed.css FeedStory.js FeedStory.test.js FeedAPI.js profile/ index.js Profile.js ProfileHeader.js ProfileHeader.css ProfileAPI.js The definition of a ¡°feature¡± is not universal, and it is up to you to choose the granularity. If you can't come up with a list of top-level folders, you can ask the users of your product what major parts it consists of, and use their mental model as a blueprint.
Grouping by file type
Another popular way to structure projects is to group similar files together, for example: api/ APIUtils.js APIUtils.test.js ProfileAPI.js UserAPI.js components/ Avatar.js Avatar.css Feed.js Feed.css FeedStory.js FeedStory.test.js Profile.js ProfileHeader.js ProfileHeader.css Some people also prefer to go further, and separate components into different folders depending on their role in the application. For example, Atomic Design is a design methodology built on this principle. Remember that it's often more productive to treat such methodologies as helpful examples rather than strict rules to follow.
Avoid too much nesting
There are many pain points associated with deep directory nesting in JavaScript projects. It becomes harder to write relative imports between them, or to update those imports when the files are moved. Unless you have a very compelling reason to use a deep folder structure, consider limiting yourself to a maximum of three or four nested folders within a single project. Of course, this is only a recommendation, and it may not be relevant to your project.
Don't overthink it
If you're just starting a project, don't spend more than five minutes on choosing a file structure. Pick any of the above approaches (or come up with your own) and start writing code! You'll likely want to rethink it anyway after you've written some real code. If you feel completely stuck, start by keeping all files in a single folder. Eventually it will grow large enough that you will want to separate some files from the rest. By that time you'll have enough knowledge to tell which files you edit together most often. In general, it is a good idea to keep files that often change together close to each other. This principle is called ¡°colocation¡±. As projects grow larger, they often use a mix of both of the above approaches in practice. So choosing the ¡°right¡± one in the beginning isn't very important.

Versioning Policy

React follows semantic versioning (semver) principles. That means that with a version number x.y.z:
  • When releasing critical bug fixes, we make a patch release by changing the z number (ex: 15.6.2 to 15.6.3).
  • When releasing new features or non-critical fixes, we make a minor release by changing the y number (ex: 15.6.2 to 15.7.0).
  • When releasing breaking changes, we make a major release by changing the x number (ex: 15.6.2 to 16.0.0).
Major releases can also contain new features, and any release can include bug fixes. Minor releases are the most common type of release.
This versioning policy does not apply to prerelease builds in the Next or Experimental channels. Learn more about prereleases.

Breaking Changes

Breaking changes are inconvenient for everyone, so we try to minimize the number of major releases ¨C for example, React 15 was released in April 2016 and React 16 was released in September 2017, and React 17 was released in October 2020. Instead, we release new features in minor versions. That means that minor releases are often more interesting and compelling than majors, despite their unassuming name.

Commitment to Stability

As we change React over time, we try to minimize the effort required to take advantage of new features. When possible, we'll keep an older API working, even if that means putting it in a separate package. For example, mixins have been discouraged for years but they're supported to this day via create-react-class and many codebases continue to use them in stable, legacy code. Over a million developers use React, collectively maintaining millions of components. The Facebook codebase alone has over 50,000 React components. That means we need to make it as easy as possible to upgrade to new versions of React; if we make large changes without a migration path, people will be stuck on old versions. We test these upgrade paths on Facebook itself ¨C if our team of less than 10 people can update 50,000+ components alone, we hope the upgrade will be manageable for anyone using React. In many cases, we write automated scripts to upgrade component syntax, which we then include in the open-source release for everyone to use.

Gradual Upgrades via Warnings

Development builds of React include many helpful warnings. Whenever possible, we add warnings in preparation for future breaking changes. That way, if your app has no warnings on the latest release, it will be compatible with the next major release. This allows you to upgrade your apps one component at a time. Development warnings won't affect the runtime behavior of your app. That way, you can feel confident that your app will behave the same way between the development and production builds ¡ª the only differences are that the production build won't log the warnings and that it is more efficient. (If you ever notice otherwise, please file an issue.)

What Counts as a Breaking Change?

In general, we don't bump the major version number for changes to:
  • Development warnings. Since these don't affect production behavior, we may add new warnings or modify existing warnings in between major versions. In fact, this is what allows us to reliably warn about upcoming breaking changes.
  • APIs starting with unstable_. These are provided as experimental features whose APIs we are not yet confident in. By releasing these with an unstable_ prefix, we can iterate faster and get to a stable API sooner.
  • Alpha and canary versions of React. We provide alpha versions of React as a way to test new features early, but we need the flexibility to make changes based on what we learn in the alpha period. If you use these versions, note that APIs may change before the stable release.
  • Undocumented APIs and internal data structures. If you access internal property names like __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED or __reactInternalInstance$uk43rzhitjg, there is no warranty. You are on your own.
This policy is designed to be pragmatic: certainly, we don't want to cause headaches for you. If we bumped the major version for all of these changes, we would end up releasing more major versions and ultimately causing more versioning pain for the community. It would also mean that we can't make progress in improving React as fast as we'd like. That said, if we expect that a change on this list will cause broad problems in the community, we will still do our best to provide a gradual migration path.

If a Minor Release Includes No New Features, Why Isn't It a Patch?

It's possible that a minor release will not include new features. This is allowed by semver, which states ¡±[a minor version] MAY be incremented if substantial new functionality or improvements are introduced within the private code. It MAY include patch level changes.¡± However, it does raise the question of why these releases aren't versioned as patches instead. The answer is that any change to React (or other software) carries some risk of breaking in unexpected ways. Imagine a scenario where a patch release that fixes one bug accidentally introduces a different bug. This would not only be disruptive to developers, but also harm their confidence in future patch releases. It's especially regrettable if the original fix is for a bug that is rarely encountered in practice. We have a pretty good track record for keeping React releases free of bugs, but patch releases have an even higher bar for reliability because most developers assume they can be adopted without adverse consequences. For these reasons, we reserve patch releases only for the most critical bugs and security vulnerabilities. If a release includes non-essential changes ¡ª such as internal refactors, changes to implementation details, performance improvements, or minor bugfixes ¡ª we will bump the minor version even when there are no new features.

Virtual DOM and Internals

What is the Virtual DOM?

The virtual DOM (VDOM) is a programming concept where an ideal, or ¡°virtual¡±, representation of a UI is kept in memory and synced with the ¡°real¡± DOM by a library such as ReactDOM. This process is called reconciliation. This approach enables the declarative API of React: You tell React what state you want the UI to be in, and it makes sure the DOM matches that state. This abstracts out the attribute manipulation, event handling, and manual DOM updating that you would otherwise have to use to build your app. Since ¡°virtual DOM¡± is more of a pattern than a specific technology, people sometimes say it to mean different things. In React world, the term ¡°virtual DOM¡± is usually associated with React elements since they are the objects representing the user interface. React, however, also uses internal objects called ¡°fibers¡± to hold additional information about the component tree. They may also be considered a part of ¡°virtual DOM¡± implementation in React.

Is the Shadow DOM the same as the Virtual DOM?

No, they are different. The Shadow DOM is a browser technology designed primarily for scoping variables and CSS in web components. The virtual DOM is a concept implemented by libraries in JavaScript on top of browser APIs.

What is ¡°React Fiber¡±?

Fiber is the new reconciliation engine in React 16. Its main goal is to enable incremental rendering of the virtual DOM. Read more.