With our component plan worked out, it's now time to start updating our app from a completely static UI to one that actually allows us to interact and change things. In this article we'll do this, digging into events and state along the way, and ending up with an app in which we can successfully add and delete tasks, and toggle tasks as completed.
If you've only written vanilla JavaScript before now, you might be used to having a separate JavaScript file, where you query for some DOM nodes and attach listeners to them. For example:
In React, we write event handlers directly on the elements in our JSX, like this:
Note: This may seem counter-intuitive regarding best-practice advice that tends to advise against use of inline event handlers on HTML, but remember that JSX is actually part of your JavaScript.
In the above example, we're adding an onClick attribute to the <button> element. The value of that attribute is a function that triggers a simple alert.
The onClick attribute has special meaning here: it tells React to run a given function when the user clicks on the button. There are a couple of other things to note:
The camel-cased nature of onClick is important — JSX will not recognize onclick (again, it is already used in JavaScript for a specific purpose, which is related but different — standard handler properties).
All browser events follow this format in JSX – on, followed by the name of the event.
Let's apply this to our app, starting in the Form.js component.
At the top of the Form() component function, create a function named handleSubmit(). This function should . After that, it should trigger an alert(), which can say whatever you'd like. It should end up looking something like this:
To use this function, add an onSubmit attribute to the element, and set its value to the handleSubmit function:
Now if you head back to your browser and click on the "Add" button, your browser will show you an alert dialog with the words "Hello, world!" — or whatever you chose to write there.
In React applications, interactivity is rarely confined to just one component: events that happen in one component will affect other parts of the app. When we start giving ourselves the power to make new tasks, things that happen in the <Form /> component will affect the list rendered in <App />.
We want our handleSubmit() function to ultimately help us create a new task, so we need a way to pass information from <Form /> to <App />. We can't pass data from child to parent in the same way as we pass data from parent to child using standard props. Instead, we can write a function in <App /> that will expect some data from our form as an input, then pass that function to <Form /> as a prop. This function-as-a-prop is called a callback prop. Once we have our callback prop, we can call it inside <Form /> to send the right data to <App />.
Inside the top of our App() component function, create a function named addTask() which has a single parameter of name:
Next, we'll pass addTask() into <Form /> as a prop. The prop can have whatever name you want, but pick a name you'll understand later. Something like addTask works, because it matches the name of the function as well as what the function will do. Your <Form /> component call should be updated as follows:
Finally, you can use this prop inside the handleSubmit() function in your <Form /> component! Update it as follows:
Clicking on the "Add" button in your browser will prove that the addTask() callback function works, but it'd be nice if we could get the alert to show us what we're typing in our input field! This is what we'll do next.
Note: We decided to name our callback prop addTask to make it easy to understand what the prop will do. Another common convention you may well come across in React code is to prefix callback prop names with the word on, followed by the name of the event that will cause them to be run. For instance, we could have given our form a prop of onSubmit with the value of addTask.
So far, we've used props to pass data through our components and this has served us just fine. Now that we're dealing with user input and data updates, however, we need something more.
For one thing, props come from the parent of a component. Our <Form /> will not be inheriting a new name for our task; our <input /> element lives directly inside of <Form />, so <Form/> will be directly responsible for creating that new name. We can't ask <Form /> to spontaneously create its own props, but we can ask it to track some of its own data for us. Data such as this, which a component itself owns, is called state. State is another powerful tool for React because components not only own state, but can update it later. It's not possible to update the props a component receives; only to read them.
React provides a variety of special functions that allow us to provide new capabilities to components, like state. These functions are called hooks, and the useState hook, as its name implies, is precisely the one we need in order to give our component some state.
To use a React hook, we need to import it from the react module. In Form.js, change your very first line so that it reads like this:
This allows us to import the useState() function by itself, and utilize it anywhere in this file.
useState() creates a piece of state for a component, and its only parameter determines the initial value of that state. It returns two things: the state, and a function that can be used to update the state later.
This is a lot to take in at once, so let's try it out. We're going to make ourselves a name state, and a function for updating the name state.
Write the following above your handleSubmit() function, inside Form():
What's going on in this line of code?
We are setting the initial name value as "Use hooks!".
We are defining a function whose job is to modify name, called setName().
You can see the name state in action right away. Add a value attribute to the form's input, and set its value to name. Your browser will render "Use hooks!" inside the input.
Change "Use hooks!" to an empty string once you're done; this is what we want for our initial state.
Before we can change the value of name, we need to capture a user's input as they type. For this, we can listen to the onChange event. Let's write a handleChange() function, and listen for it on the <input /> tag.
Currently, your input's value will not change as you type, but your browser will log the word "Typing!" to the JavaScript console, so we know our event listener is attached to the input. In order to change the input's value, we have to use our handleChange() function to update our name state.
To read the contents of the input field as they change, you can access the input's value property. We can do this inside handleChange() by reading e.target.value. e.target represents the element that fired the change event — that's our input. So, value is the text inside it.
You can console.log() this value to see it in your browser's console.
Logging isn't enough — we want to actually store the updated state of the name as the input value changes! Change the console.log() to setName(), as shown below:
Now we need to change our handleSubmit() function so that it calls props.addTask with name as an argument — remember our callback prop? This will serve to send the task back to the App component, so we can add it to our list of tasks at some later date. As a matter of good practice, you should clear the input after your form submits, so we'll call setName() again with an empty string to do so:
At last, you can type something into the input field in your browser and click Add — whatever you typed will appear in an alert dialog.
Your Form.js file should now read like this:
Note: One thing you'll notice is that you are able to submit empty tasks by just pressing the Add button without entering a task name. Can you think of a way to disallow empty tasks from being added? As a hint, you probably need to add some kind of check into the handleSubmit() function.
Now that we've practiced with events, callback props, and hooks we're ready to write functionality that will allow a user to add a new task from their browser.
Import useState into App.js, so that we can store our tasks in state — update your React import line to the following:
We want to pass props.tasks into the useState() hook – this will preserve its initial state. Add the following right at the top of your App() function definition:
Now, we can change our taskList mapping so that it is the result of mapping tasks, instead of props.tasks. Your taskList constant declaration should now look like so:
We've now got a setTasks hook that we can use in our addTask() function to update our list of tasks. There's one problem however: we can't just pass the name argument of addTask() into setTasks, because tasks is an array of objects and name is a string. If we tried to do this, the array would be replaced with the string.
First of all, we need to put name into an object that has the same structure as our existing tasks. Inside of the addTask() function, we will make a newTask object to add to the array.
We then need to make a new array with this new task added to it and then update the state of the tasks data to this new state. To do this, we can use spread syntax to , and add our object at the end. We then pass this array into setTasks() to update the state.
Putting that all together, your addTask() function should read like so:
Now you can use the browser to add a task to our data! Type anything into the form and click "Add" (or press the Enter key) and you'll see your new todo item appear in the UI!
However, we have another problem: our addTask() function is giving each task the same id. This is bad for accessibility, and makes it impossible for React to tell future tasks apart with the key prop. In fact, React will give you a warning in your DevTools console — "Warning: Encountered two children with the same key..."
We need to fix this. Making unique identifiers is a hard problem – one for which the JavaScript community has written some helpful libraries. We'll use because it's tiny, and it works.
Make sure you're in the root directory of your application and run the following terminal command:
Note: If you're using yarn, you'll need the following instead: yarn add nanoid
Now we can import nanoid into the top of App.js so we can use it to create unique IDs for our new tasks. First of all, include the following import line at the top of App.js:
Now let's update addTask() so that each task ID becomes a prefix todo- plus a unique string generated by nanoid. Update your newTask constant declaration to this:
Save everything, and try your app again — now you can add tasks without getting that warning about duplicate IDs.
Now that we can add new tasks, you may notice a problem: our heading reads 3 tasks remaining, no matter how many tasks we have! We can fix this by counting the length of taskList and changing the text of our heading accordingly.
Add this inside your App() definition, before the return statement:
Hrm. This is almost right, except that if our list ever contains a single task, the heading will still use the word "tasks". We can make this a variable, too. Update the code you just added as follows:
Now you can replace the list heading's text content with the headingText variable. Update your <h2> like so:
You might notice that, when you click on a checkbox, it checks and unchecks appropriately. As a feature of HTML, the browser knows how to remember which checkbox inputs are checked or unchecked without our help. This feature hides a problem, however: toggling a checkbox doesn't change the state in our React application. This means that the browser and our app are now out-of-sync. We have to write our own code to put the browser back in sync with our app.
Before we fix the problem, let's observe it happening.
We'll start by writing a toggleTaskCompleted() function in our App() component. This function will have an id parameter, but we're not going to use it yet. For now, we'll log the first task in the array to the console – we're going to inspect what happens when we check or uncheck it in our browser:
Add this just above your taskList constant declaration:
Next, we'll add toggleTaskCompleted to the props of each <Todo /> component rendered inside our taskList; update it like so:
Next, go over to your Todo.js component and add an onChange handler to your <input /> element, which should use an anonymous function to call props.toggleTaskCompleted() with a parameter of props.id. The <input /> should now look like this:
Save everything and return to your browser and notice that our first task, Eat, is checked. Open your JavaScript console, then click on the checkbox next to Eat. It unchecks, as we expect. Your JavaScript console, however, will log something like this:
The checkbox unchecks in the browser, but our console tells us that Eat is still completed. We will fix that next!
Let's revisit our toggleTaskCompleted() function in App.js. We want it to change the completed property of only the task that was toggled, and leave all the others alone. To do this, we'll map() over the task list and just change the one we completed.
Update your toggleTaskCompleted() function to the following:
Here, we define an updatedTasks constant that maps over the original tasks array. If the task's id property matches the id provided to the function, we use to create a new object, and toggle the checked property of that object before returning it. If it doesn't match, we return the original object.
Then we call setTasks() with this new array in order to update our state.
Deleting a task will follow a similar pattern to toggling its completed state: We need to define a function for updating our state, then pass that function into <Todo /> as a prop and call it when the right event happens.
Here we'll start by writing a deleteTask() function in your App component. Like toggleTaskCompleted(), this function will take an id parameter, and we will log that id to the console to start with. Add the following below toggleTaskCompleted():
Next, add another callback prop to our array of <Todo /> components:
In Todo.js, we want to call props.deleteTask() when the "Delete" button is pressed. deleteTask() needs to know the ID of the task that called it, so it can delete the correct task from the state.
Update the "Delete" button inside Todo.js, like so:
Now when you click on any of the "Delete" buttons in the app, your browser console should log the ID of the related task.
Now that we know deleteTask() is invoked correctly, we can call our setTasks() hook in deleteTask() to actually delete that task from the app's state as well as visually in the app UI. Since setTasks() expects an array as an argument, we should provide it with a new array that copies the existing tasks, excluding the task whose ID matches the one passed into deleteTask().
This is a perfect opportunity to use . We can test each task, and exclude a task from the new array if its id prop matches the id parameter passed into deleteTask().
Update the deleteTask() function inside your App.js file as follows:
Try your app out again. Now you should be able to delete a task from your app!
React interactivity:
Editing, filtering, conditional rendering
As we near the end of our React journey (for now at least), we'll add the finishing touches to the main areas of functionality in our Todo list app. This includes allowing you to edit existing tasks, and filtering the list of tasks between all, completed, and incomplete tasks. We'll look at conditional UI rendering along the way.
We don't have a user interface for editing the name of a task yet. We'll get to that in a moment. To start with, we can at least implement an editTask() function in App.js. It'll be similar to deleteTask() because it'll take an id to find its target object, but it'll also take a newName property containing the name to update the task to. We'll use instead of because we want to return a new array with some changes, instead of deleting something from the array.
Add the editTask() function inside your App component, in the same place as the other functions:
Pass editTask into our <Todo /> components as a prop in the same way we did with deleteTask:
Now open Todo.js. We're going to do some refactoring.
In order to allow users to edit a task, we have to provide a user interface for them to do so. First, import useState into the Todo component like we did before with the App component, by updating the first import statement to this:
We'll now use this to set an isEditing state, the default state of which should be false. Add the following line just inside the top of your Todo(props) { … } component definition:
Next, we're going to rethink the <Todo /> component — from now on, we want it to display one of two possible "templates", rather than the single template it's used so far:
The "view" template, when we are just viewing a todo; this is what we've used in the tutorial thus far.
The "editing" template, when we are editing a todo. We're about to create this.
Copy this block of code into the Todo() function, beneath your useState() hook but above the return statement:
We've now got the two different template structures — "edit" and "view" — defined inside two separate constants. This means that the return statement of <Todo /> is now repetitious — it also contains a definition of the "view" template. We can clean this up by using conditional rendering to determine which template the component returns, and is therefore rendered in the UI.
In JSX, we can use a condition to change what is rendered by the browser. To write a condition in JSX, we can use a .
In the case of our <Todo /> component, our condition is "Is this task being edited?" Change the return statement inside Todo() so that it reads like so:
Your browser should render all your tasks just like before. To see the editing template, you will have to change the default isEditing state from false to true in your code for now; we will look at making the edit button toggle this in the next section!
At long last, we are ready to make our final core feature interactive. To start with, we want to call setEditing() with a value of true when a user presses the "Edit" button in our viewTemplate, so that we can switch templates.
Update the "Edit" button in the viewTemplate like so:
Now we'll add the same onClick handler to the "Cancel" button in the editingTemplate, but this time we'll set isEditing to false so that it switches us back to the view template.
Update the "Cancel" button in the editingTemplate like so:
With this code in place, you should be able to press the "Edit" and "Cancel" buttons in your todo items to toggle between templates.
The next step is to actually make the editing functionality work.
Much of what we're about to do will mirror the work we did in Form.js: as the user types in our new input field, we need to track the text they enter; once they submit the form, we need to use a callback prop to update our state with the new name of the task.
We'll start by making a new hook for storing and setting the new name. Still in Todo.js, put the following underneath the existing hook:
Next, create a handleChange() function that will set the new name; put this underneath the hooks but before the templates:
Now we'll update our editingTemplate's <input /> field, setting a value attribute of newName, and binding our handleChange() function to its onChange event. Update it as follows:
Finally, we need to create a function to handle the edit form's onSubmit event; add the following just below the previous function you added:
Remember that our editTask() callback prop needs the ID of the task we're editing as well as its new name.
Bind this function to the form's submit event by adding the following onSubmit handler to the editingTemplate's <form>:
You should now be able to edit a task in your browser!
Now that our main features are complete, we can think about our filter buttons. Currently, they repeat the "All" label, and they have no functionality! We will be reapplying some skills we used in our <Todo /> component to:
Create a hook for storing the active filter.
Render an array of <FilterButton /> elements that allow users to change the active filter between all, completed, and incomplete.
Add a new hook to your App() function that reads and sets a filter. We want the default filter to be All because all of our tasks should be shown initially:
Our goal right now is two-fold:
Each filter should have a unique name.
Each filter should have a unique behavior.
A JavaScript object would be a great way to relate names to behaviors: each key is the name of a filter; each property is the behavior associated with that name.
At the top of App.js, beneath our imports but above our App() function, let's add an object called FILTER_MAP:
The values of FILTER_MAP are functions that we will use to filter the tasks data array:
The All filter shows all tasks, so we return true for all tasks.
The Active filter shows tasks whose completed prop is false.
Beneath our previous addition, add the following — here we are using the method to collect an array of FILTER_NAMES:
Note: We are defining these constants outside our App() function because if they were defined inside it, they would be recalculated every time the <App /> component re-renders, and we don't want that. This information will never change no matter what our application does.
Now that we have the FILTER_NAMES array, we can use it to render all three of our filters. Inside the App() function we can create a constant called filterList, which we will use to map over our array of names and return a <FilterButton /> component. Remember, we need keys here, too.
Add the following underneath your taskList constant declaration:
Now we'll replace the three repeated <FilterButton />s in App.js with this filterList. Replace the following:
With this:
This won't work yet. We've got a bit more work to do first.
To make our filter buttons interactive, we should consider what props they need to utilize.
We know that the <FilterButton /> should report whether it is currently pressed, and it should be pressed if its name matches the current value of our filter state.
We know that the <FilterButton /> needs a callback to set the active filter. We can make direct use of our setFilter hook.
Update your filterList constant as follows:
In the same way as we did earlier with our <Todo /> component, we now have to update FilterButton.js to utilize the props we have given it. Do each of the following, and remember to use curly braces to read these variables!
Replace all with {props.name}.
Set the value of aria-pressed to {props.isPressed}.
With all of that done, your FilterButton() function should read like this:
Visit your browser again. You should see that the different buttons have been given their respective names. When you press a filter button, you should see its text take on a new outline — this tells you it has been selected. And if you look at your DevTool's Page Inspector while clicking the buttons, you'll see the aria-pressed attribute values change accordingly.
However, our buttons still don't actually filter the todos in the UI! Let's finish this off.
Right now, our taskList constant in App() maps over the tasks state and returns a new <Todo /> component for all of them. This is not what we want! A task should only render if it is included in the results of applying the selected filter. Before we map over the tasks state, we should filter it (with ) to eliminate objects we don't want to render.
Update your taskList like so:
In order to decide which callback function to use in Array.prototype.filter(), we access the value in FILTER_MAP that corresponds to the key of our filter state. When filter is All, for example, FILTER_MAP[filter] will evaluate to () => true.
Choosing a filter in your browser will now remove the tasks that do not meet its criteria. The count in the heading above the list will also change to reflect the list!
So that's it — our app is now functionally complete. However, now that we've implemented all of our features, we can make a few improvements to ensure that a wider range of users can use our app. Our next article rounds things off for our React tutorials by looking at including focus management in React, which can improve usability and reduce confusion for both keyboard-only and screenreader users.
// near the top of the `Form` component
function handleChange(e) {
console.log("Typing!");
}
// Down in the return statement
<input
type="text"
id="new-todo-input"
className="input input__lg"
name="text"
autoComplete="off"
value={name}
onChange={handleChange}
/>
function handleChange(e) {
console.log(e.target.value);
}
function handleChange(e) {
setName(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
props.addTask(name);
setName("");
}
import React, { useState } from "react";
function Form(props) {
const [name, setName] = useState("");
function handleChange(e) {
setName(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
props.addTask(name);
setName("");
}
return (
<form onSubmit={handleSubmit}>
<h2 className="label-wrapper">
<label htmlFor="new-todo-input" className="label__lg">
What needs to be done?
</label>
</h2>
<input
type="text"
id="new-todo-input"
className="input input__lg"
name="text"
autoComplete="off"
value={name}
onChange={handleChange}
/>
<button type="submit" className="btn btn__primary btn__lg">
Add
</button>
</form>
);
}
export default Form;
function toggleTaskCompleted(id) {
const updatedTasks = tasks.map(task => {
// if this task has the same ID as the edited task
if (id === task.id) {
// use object spread to make a new object
// whose `completed` prop has been inverted
return {...task, completed: !task.completed}
}
return task;
});
setTasks(updatedTasks);
}
function deleteTask(id) {
const remainingTasks = tasks.filter(task => id !== task.id);
setTasks(remainingTasks);
}
function editTask(id, newName) {
const editedTaskList = tasks.map(task => {
// if this task has the same ID as the edited task
if (id === task.id) {
//
return {...task, name: newName}
}
return task;
});
setTasks(editedTaskList);
}
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:
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 to define a component:
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:
However, elements can also represent user-defined components:
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:
Let's recap what happens in this example:
We call ReactDOM.render() with the <Welcome name="Sara" /> element.
React calls the Welcome component with {name: 'Sara'} as the props.
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:
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:
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:
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:
Next, we will extract a UserInfo component that renders an Avatar next to the user's name:
This lets us simplify Comment even further:
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 , it must never modify its own props. Consider this sum function:
Such functions are called 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:
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.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Our Welcome component returns a <h1>Hello, Sara</h1> element as the result.
React DOM efficiently updates the DOM to match <h1>Hello, Sara</h1>.
function withdraw(account, amount) {
account.total -= amount;
}
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.
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:
Creating React Elements
We recommend using JSX to describe what your UI should look like. Each JSX element is just syntactic sugar for calling . You will not typically invoke the following methods directly if you are using JSX.
See Using React without JSX for more information.
Transforming Elements
React provides several APIs for manipulating elements:
Fragments
React also provides a component for rendering multiple elements without a wrapper.
Refs
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.
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
Reference
React.Component
React.Component is the base class for React components when they are defined using :
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 . The difference between them is that 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 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
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, useReducer 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.
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()
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 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()
Clone and return a new React element using element as the starting point. config should contain all new props, key, or ref. 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 if no key and ref present in the config.
React.cloneElement() is almost equivalent to:
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. The new ref or key will replace old ones if present.
This API was introduced as a replacement of the deprecated React.addons.cloneWithProps().
createFactory()
Return a function that produces React elements of a given type. Like , 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 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()
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
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
Like but does not return an array.
React.Children.count
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
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 because it is an array rather than a React element.
React.Children.toArray
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:
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. embed:16-3-release-blog-post/create-ref-example.js
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.
embed:reference-react-forward-ref.js
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 explaining how to use it in more detail.
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>:
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.
Animation Add-Ons
Note:
ReactTransitionGroup and ReactCSSTransitionGroup have been moved to the react-transition-group package that is maintained by the community. Its 1.x branch is completely API-compatible with the existing addons. Please file bugs and feature requests in the new repository.
The ReactTransitionGroup add-on component is a low-level API for animation, and ReactCSSTransitionGroup is an add-on component for easily implementing basic CSS animations and transitions.
High-level API: ReactCSSTransitionGroup
ReactCSSTransitionGroup is a high-level API based on and is an easy way to perform CSS transitions and animations when a React component enters or leaves the DOM. It's inspired by the excellent library.
Importing
Note:
You must provide the key attribute for all children of ReactCSSTransitionGroup, even when only rendering a single item. This is how React will determine which children have entered, left, or stayed.
In this component, when a new item is added to ReactCSSTransitionGroup it will get the example-enter CSS class and the example-enter-active CSS class added in the next tick. This is a convention based on the transitionName prop.
You can use these classes to trigger a CSS animation or transition. For example, try adding this CSS and adding a new list item:
You'll notice that animation durations need to be specified in both the CSS and the render method; this tells React when to remove the animation classes from the element and -- if it's leaving -- when to remove the element from the DOM.
Animate Initial Mounting
ReactCSSTransitionGroup provides the optional prop transitionAppear, to add an extra transition phase at the initial mount of the component. There is generally no transition phase at the initial mount as the default value of transitionAppear is false. The following is an example which passes the prop transitionAppear with the value true.
During the initial mount ReactCSSTransitionGroup will get the example-appear CSS class and the example-appear-active CSS class added in the next tick.
At the initial mount, all children of the ReactCSSTransitionGroup will appear but not enter. However, all children later added to an existing ReactCSSTransitionGroup will enter but not appear.
Note:
The prop transitionAppear was added to ReactCSSTransitionGroup in version 0.13. To maintain backwards compatibility, the default value is set to false.
However, the default values of transitionEnter and transitionLeave are true so you must specify transitionEnterTimeout and transitionLeaveTimeout
Custom Classes
It is also possible to use custom class names for each of the steps in your transitions. Instead of passing a string into transitionName you can pass an object containing either the enter and leave class names, or an object containing the enter, enter-active, leave-active, and leave class names. If only the enter and leave classes are provided, the enter-active and leave-active classes will be determined by appending '-active' to the end of the class name. Here are two examples using custom classes:
Animation Group Must Be Mounted To Work
In order for it to apply transitions to its children, the ReactCSSTransitionGroup must already be mounted in the DOM or the prop transitionAppear must be set to true.
The example below would not work, because the ReactCSSTransitionGroup is being mounted along with the new item, instead of the new item being mounted within it. Compare this to the section above to see the difference.
Animating One or Zero Items
In the example above, we rendered a list of items into ReactCSSTransitionGroup. However, the children of ReactCSSTransitionGroup can also be one or zero items. This makes it possible to animate a single element entering or leaving. Similarly, you can animate a new element replacing the current element. For example, we can implement a simple image carousel like this:
Disabling Animations
You can disable animating enter or leave animations if you want. For example, sometimes you may want an enter animation and no leave animation, but ReactCSSTransitionGroup waits for an animation to complete before removing your DOM node. You can add transitionEnter={false} or transitionLeave={false} props to ReactCSSTransitionGroup to disable these animations.
Note:
When using ReactCSSTransitionGroup, there's no way for your components to be notified when a transition has ended or to perform any more complex logic around animation. If you want more fine-grained control, you can use the lower-level ReactTransitionGroup API which provides the hooks you need to do custom transitions.
Low-level API: ReactTransitionGroup
Importing
ReactTransitionGroup is the basis for animations. When children are declaratively added or removed from it (as in the ), special lifecycle methods are called on them.
Rendering a Different Component
ReactTransitionGroup renders as a span by default. You can change this behavior by providing a component prop. For example, here's how you would render a <ul>:
Any additional, user-defined, properties will become properties of the rendered component. For example, here's how you would render a <ul> with CSS class:
Every DOM component that React can render is available for use. However, component does not need to be a DOM component. It can be any React component you want; even ones you've written yourself! Just write component={List} and your component will receive this.props.children.
Rendering a Single Child
People often use ReactTransitionGroup to animate mounting and unmounting of a single child such as a collapsible panel. Normally ReactTransitionGroup wraps all its children in a span (or a custom component as described above). This is because any React component has to return a single root element, and ReactTransitionGroup is no exception to this rule.
However if you only need to render a single child inside ReactTransitionGroup, you can completely avoid wrapping it in a <span> or any other DOM component. To do this, create a custom component that renders the first child passed to it directly:
Now you can specify FirstChild as the component prop in <ReactTransitionGroup> props and avoid any wrappers in the result DOM:
This only works when you are animating a single child in and out, such as a collapsible panel. This approach wouldn't work when animating multiple children or replacing the single child with another child, such as an image carousel. For an image carousel, while the current image is animating out, another image will animate in, so <ReactTransitionGroup> needs to give them a common DOM parent. You can't avoid the wrapper for multiple children, but you can customize the wrapper with the component prop as described above.
Reference
componentWillAppear()
This is called at the same time as componentDidMount() for components that are initially mounted in a TransitionGroup. It will block other animations from occurring until callback is called. It is only called on the initial render of a TransitionGroup.
componentDidAppear()
This is called after the callback function that was passed to componentWillAppear is called.
componentWillEnter()
This is called at the same time as componentDidMount() for components added to an existing TransitionGroup. It will block other animations from occurring until callback is called. It will not be called on the initial render of a TransitionGroup.
componentDidEnter()
This is called after the callback function that was passed to is called.
componentWillLeave()
This is called when the child has been removed from the ReactTransitionGroup. Though the child has been removed, ReactTransitionGroup will keep it in the DOM until callback is called.
componentDidLeave()
This is called when the willLeavecallback is called (at the same time as componentWillUnmount()).
Accessibility in React
At this point, we've accomplished all of the features we set out to implement. A user can add a new task, check and uncheck tasks, delete tasks, or edit task names. And they can filter their task list by all, active, or completed tasks.
Or, at least: they can do all of these things with a mouse. Unfortunately, these features are not very accessible to keyboard-only users. Let's explore this now.
PureRenderMixin
Note:
PureRenderMixin is a legacy add-on. Use React.PureComponent instead.
Importing
CDN Links
Both React and ReactDOM are available over a CDN.
The versions above are only meant for development, and are not suitable for production. Minified and optimized production versions of React are available at:
To load a specific version of react and react-dom, replace 17 with the version number.
Add-Ons
Note:
React.addons entry point is deprecated as of React v15.5. The add-ons have moved to separate modules, and some of them have been deprecated.
The React add-ons are a collection of useful utility modules for building React apps. These should be considered experimental and tend to change more often than the core.
Start by clicking on the input at the top of our app, as if you're going to add a new task. You'll see a thick, dashed outline around that input. This outline is your visual indicator that the browser is currently focused on this element. Press the Tab key, and you will see the outline appear around the "Add" button beneath the input. This shows you that the browser's focus has moved.
Press Tab a few more times, and you will see this dashed focus indicator move between each of the filter buttons. Keep going until the focus indicator is around the first "Edit" button. Press Enter.
The <Todo /> component will switch templates, as we designed, and you'll see a form that lets us edit the name of the task.
But where did our focus indicator go?
When we switch between templates in our <Todo /> component, we completely remove the elements that were there before to replace them with something else. That means the element that we were focused on vanishes, and nothing is in focus at all. This could confuse a wide variety of users — particularly users who rely on the keyboard, or users who use a screen reader.
To improve the experience for keyboard and screen-reader users, we should manage the browser's focus ourselves.
When a user toggles a <Todo/> template from viewing to editing, we should focus on the <input> used to rename it; when they toggle back from editing to viewing, we should move focus back to the "Edit" button.
In order to focus on an element in our DOM, we need to tell React which element we want to focus on and how to find it. React's useRef hook creates an object with a single property: current. This property can be a reference to anything we want and look that reference up later. It's particularly useful for referring to DOM elements.
Change the import statement at the top of Todo.js so that it includes useRef:
Then, create two new constants beneath the hooks in your Todo() function. Each should be a ref – one for the "Edit" button in the view template and one for the edit field in the editing template.
These refs have a default value of null because they will not have value until we attach them to their respective elements. To do that, we'll add an attribute of ref to each element, and set their values to the appropriately named ref objects.
The textbox <input> in your editing template should be updated like this:
The "Edit" button in your view template should read like this:
To use our refs for their intended purpose, we need to import another React hook: useEffect(). useEffect() is so named because it runs after React renders a given component, and will run any side-effects that we'd like to add to the render process, which we can't run inside the main function body. useEffect() is useful in the current situation because we cannot focus on an element until after the <Todo /> component renders and React knows where our refs are.
Change the import statement of Todo.js again to add useEffect:
useEffect() takes a function as an argument; this function is executed after the component renders. Let's see this in action; put the following useEffect() call just above the return statement in the body of Todo(), and pass into it a function that logs the words "side effect" to your console:
To illustrate the difference between the main render process and code run inside useEffect(), add another log – put this one below the previous addition:
Now, open the app in your browser. You should see both messages in your console, with each one repeating three times. Note how "main render" logged first, and "side effect" logged second, even though the "side effect" log appears first in the code.
That's it for our experimentation for now. Delete console.log("main render") now, and lets move on to implementing our focus management.
Now that we know our useEffect() hook works, we can manage focus with it. As a reminder, we want to focus on the editing field when we switch to the editing template.
Update your existing useEffect() hook so that it reads like this:
These changes make it so that, if isEditing is true, React reads the current value of the editFieldRef and moves browser focus to it. We also pass an array into useEffect() as a second argument. This array is a list of values useEffect() should depend on. With these values included, useEffect() will only run when one of those values changes. We only want to change focus when the value of isEditing changes.
Try it now, and you'll see that when you click an "Edit" button, focus moves to the corresponding edit <input>!
At first glance, getting React to move focus back to our "Edit" button when the edit is saved or cancelled appears deceptively easy. Surely we could add a condition to our useEffect to focus on the edit button if isEditing is false? Let's try it now — update your useEffect() call like so:
This kind of mostly works. Head back to your browser and you'll see that your focus moves between Edit <input> and "Edit" button as you start and end an edit. However, you may have noticed a new problem — the "Edit" button in the final <Todo /> component is focussed immediately on page load, before we even interact with the app!
Our useEffect() hook is behaving exactly as we designed it: it runs as soon as the component renders, sees that isEditing is false, and focuses the "Edit" button. Because there are three instances of <Todo />, we see focus on the last "Edit" button.
We need to refactor our approach so that focus changes only when isEditing changes from one value to another.
In order to meet our refined criteria, we need to know not just the value of isEditing, but also when that value has changed. In order to do that, we need to be able to read the previous value of the isEditing constant. Using pseudocode, our logic should be something like this:
Paste the following code near the top of Todo.js, above your Todo() function.
Now we'll define a wasEditing constant beneath the hooks at the top of Todo(). We want this constant to track the previous value of isEditing, so we call usePrevious with isEditing as an argument:
With this constant, we can update our useEffect() hook to implement the pseudocode we discussed before — update it as follows:
Note that the logic of useEffect() now depends on wasEditing, so we provide it in the array of dependencies.
Again try using the "Edit" and "Cancel" buttons to toggle between the templates of your <Todo /> component; you'll see the browser focus indicator move appropriately, without the problem we discussed at the start of this section.
There's one last keyboard experience gap: when a user deletes a task from the list, the focus vanishes. We're going to follow a pattern similar to our previous changes: we'll make a new ref, and utilize our usePrevious() hook, so that we can focus on the list heading whenever a user deletes a task.
Sometimes, the place we want to send our focus to is obvious: when we toggled our <Todo /> templates, we had an origin point to "go back" to — the "Edit" button. In this case however, since we're completely removing elements from the DOM, we have no place to go back to. The next best thing is an intuitive location somewhere nearby. The list heading is our best choice because it's close to the list item the user will delete, and focusing on it will tell the user how many tasks are left.
Heading elements like our <h2> are not usually focusable. This isn't a problem — we can make any element programmatically focusable by adding the attribute tabindex="-1" to it. This means only focusable with JavaScript. You can't press Tab to focus on an element with a tabindex of -1 the same way you could do with a <button> or <a> element (this can be done using tabindex="0", but that's not really appropriate in this case).
Let's add the tabindex attribute — written as tabIndex in JSX — to the heading above our list of tasks, along with our headingRef:
Note: The tabindex attribute is great for accessibility edge-cases, but you should take great care to not overuse it. Only apply a tabindex to an element when you're absolutely sure that making it focusable will benefit your user in some way. In most cases, you should be utilizing elements that can naturally take focus, such as buttons, anchors, and inputs. Irresponsible usage of tabindex could have a profoundly negative impact on keyboard and screen-reader users!
We want to focus on the element associated with our ref (via the ref attribute) only when our user deletes a task from their list. That's going to require the usePrevious() hook we already used earlier on. Add it to the top of your App.js file, just below the imports:
Now add the following, above the return statement inside the App() function:
Here we are invoking usePrevious() to track the length of the tasks state, like so:
Note: Since we're now utilizing usePrevious() in two files, a good efficiency refactor would be to move the usePrevious() function into its own file, export it from that file, and import it where you need it. Try doing this as an exercise once you've got to the end.
Now that we've stored how many tasks we previously had, we can set up a useEffect() hook to run when our number of tasks changes, which will focus the heading if the number of tasks we have now is less than with it previously was — i.e. we deleted a task!
Add the following into the body of your App() function, just below your previous additions:
We only try to focus on our list heading if we have fewer tasks now than we did before. The dependencies passed into this hook ensure it will only try to re-run when either of those values (the number of current tasks, or the number of previous tasks) changes.
Now, when you delete a task in your browser, you will see our dashed focus outline appear around the heading above the list.
If your React component's render function renders the same result given the same props and state, you can use this mixin for a performance boost in some cases.
Example:
Under the hood, the mixin implements shouldComponentUpdate, in which it compares the current props and state with the next ones and returns false if the equalities pass.
Note:
This only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only mix into components which 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, shouldComponentUpdate skips updates for the whole component subtree. Make sure all the children components are also "pure".
import PureRenderMixin from "react-addons-pure-render-mixin"; // ES6
var PureRenderMixin = require("react-addons-pure-render-mixin"); // ES5 with npm
Why the crossorigin Attribute?
If you serve React from a CDN, we recommend to keep the crossorigin attribute set:
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.
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);
import ReactTransitionGroup from "react-addons-transition-group"; // ES6
var ReactTransitionGroup = require("react-addons-transition-group"); // ES5 with npm
The add-ons below are in the development (unminified) version of React only:
Perf, a performance profiling tool for finding optimization opportunities.
ReactTestUtils, simple helpers for writing test cases.
Legacy Add-ons
The add-ons below are considered legacy and their use is discouraged. They will keep working in observable future, but there is no further development.
PureRenderMixin. Use React.PureComponent instead.
shallowCompare, a helper function that performs a shallow comparison for props and state in a component to decide if a component should update. We recommend using React.PureComponent instead.
update. Use instead.
, pre-configured DOM factories to make React easier to use without JSX.
You can install the add-ons individually from npm (e.g. npm install react-addons-create-fragment) and import them:
When using React 15 or earlier from a CDN, you can use react-with-addons.js instead of react.js:
The add-ons will be available via the React.addons global (e.g. React.addons.TestUtils).
Styling and CSS
How do I add CSS classes to components?
Pass a string as the className prop:
It is common for CSS classes to depend on the component props or state:
Tip
If you often find yourself writing code like this, 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 , , , or , for example.
React
Although this tutorial doesn't use this approach, many React applications define their styles on a per-component basis, rather than in a single, monolithic stylesheet.
create-react-app makes it possible to import CSS files into JavaScript modules, so that CSS is only sent to your user when the corresponding component is rendered. For this app, we could have for example written a dedicated Form.css file to house the styles of those respective components, then imported the styles into their respective modules like this:
import createFragment from "react-addons-create-fragment"; // ES6
var createFragment = require("react-addons-create-fragment"); // ES5 with npm
This approach makes it easy to identify and manage the CSS that belongs to a specific component. However, it also fragments your stylesheet across your codebase, and this fragmentation might not be worthwhile. For larger applications with hundreds of unique views and lots of moving parts, it makes sense to limit the amount of irrelevant code that's sent to your user. You'll likely have app-wide styles and specific component styles that built on top of those.
We used console.log() to check on the state and props of our application in this tutorial, and you'll also have seen some of the useful warnings and error message that react gives you both in the CLI and your browser's JavaScript console. But there's more we can do here.
The React DevTools utility allows you to inspect the internals of your React application directly in the browser. It adds a new panel to your browser's developer tools, and with it you can inspect the state and props of various components, and even edit state and props to make immediate changes to your application.
This screenshot shows our finished application as it appears in React DevTools:
Our project being shown in React devtools
On the left, we see all of the components that make up our application, including some unique keys for the things that are rendered from arrays. On the right, we see the props and hooks that our App component utilizes. Notice, too, that the Form, FilterButton, and Todo components are indented to the right – this indicates that App is their parent. In more complex apps, this view is great for understanding parent/child relationships at a glance.
The application that we built in this tutorial utilized component props to pass data from its App component to the child components that needed it. Most of the time, props are an appropriate method for sharing data; for complex, deeply nested applications, however, they're not always best.
React provides the Context API as a way to provide data to components that need it without passing props down the component tree. There's also a useContext hook that facilitates this.
Although this tutorial doesn't mention them, it is possible to build React components using ES6 classes – these are called class components. Until the arrival of hooks, ES6 classes were the only way to bring state into components or manage rendering side effects. They're still the only way to handle certain other, more edge-case features, and they're very common in legacy React projects. The official React docs are a great place to start learning about them.
create-react-app provides some tools for testing your application out of the box — you may have deleted the relevant files earlier in the tutorial. The documentation for create-react-appcovers some basics for testing.
While routing is traditionally handled by a server and not an application on the user's computer, it is possible to configure a web application to read and update the browser's location, and render certain user interfaces. This is called client-side routing. It's possible to create many unique routes for your application (such as /home, /dashboard, or login/).
The React community has produced two major libraries for client-side routing: React Router and Reach Router.
React Router is well-suited to applications with complex routing needs, and it meets some edge cases better than Reach Router. React Router is a larger library, however.
Reach Router is well-suited to simpler applications, and automatically manages focus as the user navigates from page to page.
Focus management is essential in client-side routing — without it, keyboard users can be trapped in focus limbo, and screen-reader users may have no idea that they have moved to a new page. Because Reach Router is better for accessibility, it's a good place to start.
There's one caveat, however: these projects will be merging in the near future. When this merge happens, React Router will be the surviving project (with the addition of the focus management features of Reach).
HTML form elements work a 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:
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:
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:
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:
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:
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:
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:
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 .
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:
Note how we used the ES6 syntax to update the state key corresponding to the given input name:
It is equivalent to this ES5 code:
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.)
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, 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.
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.
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 , , or .
If you prefer to use your own text editor, you can also , 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.
If you prefer to learn by doing, start with our practical tutorial.
If you prefer to learn concepts step by step, start with our guide to main concepts.
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 . 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, 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 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, and 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 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 , as well as on the 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 with your suggestions for improvement, or tweet at the . We love hearing from you!
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 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 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 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 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 and , 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 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 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 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 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 .
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 . 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 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 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 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 . 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 . 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 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 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 , safely lint and codemod internal component usage, and 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. 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 to React even though we don't rely on either of them internally. We are actively 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.
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:
We'll create a Greeting component that displays either of these components depending on whether a user is logged in:
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:
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:
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:
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.
Inline If-Else with Conditional Operator
Another method for conditionally rendering elements inline is to use the JavaScript conditional operator .
In the example below, we use it to conditionally render a small block of text.
It can also be used for larger expressions although it is less obvious what's going on:
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:
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.
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.
There is also a new for declaring them.
Motivation
A common pattern is for a component to return a list of children. Take this example React snippet:
Legacy Context
Note:
The legacy context API will be removed in a future major version. Use the new context API introduced with version 16.3. The legacy API will continue working for all 16.x releases.
How To Use Context
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.
Portals
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
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
Lists and Keys
First, let's review how you transform lists in JavaScript.
Given the code below, we use the 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:
This code logs [2, 4, 6, 8, 10] to the console.
In React, transforming arrays into lists of elements is nearly identical.
JSX In Depth
Fundamentally, JSX just provides syntactic sugar for the React.createElement(component, props, ...children) function. The JSX code:
compiles into:
You can also use the self-closing form of the tag if there are no children. So:
compiles into:
If you want to test out how some specific JSX is converted into JavaScript, you can try out .
Using the Effect Hook
Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.
The Effect Hook lets you perform side effects in function components:
This snippet is based on the counter example from the previous page, but we added a new feature to it: we set the document title to a custom message including the number of clicks.
Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects. Whether or not you're used to calling these operations "side effects" (or just "effects"), you've likely performed them in your components before.
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(<h1>Hello, world!</h1>, document.getElementById("root"));
React also depends on requestAnimationFrame (even in test environments).
You can use the raf package to shim requestAnimationFrame:
import "raf/polyfill";
<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.
results in a <Table /> output of:
Fragments solve this problem.
Usage
which results in a correct <Table /> output of:
Short Syntax
There is a new, shorter syntax you can use for declaring fragments. It looks like empty tags:
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:
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.
This section documents a legacy API. See the new API.
Suppose you have a structure like:
In this example, we manually thread through a color prop in order to style the Button and Message components appropriately. Using context, we can pass this through the tree automatically:
By adding childContextTypes and getChildContext to MessageList (the context provider), React passes the information down automatically and any component in the subtree (in this case, Button) can access it by defining contextTypes.
If contextTypes is not defined, then context will be an empty object.
Note:
React.PropTypes has moved into a different package since React v15.5. Please use the prop-types library instead to define contextTypes.
We provide a codemod script to automate the conversion.
Parent-Child Coupling
This section documents a legacy API. See the new API.
Context can also let you build an API where parents and children communicate. For example, one library that works this way is React Router V4:
By passing down some information from the Router component, each Link and Route can communicate back to the containing Router.
Before you build components with an API similar to this, consider if there are cleaner alternatives. For example, you can pass entire React components as props if you'd like to.
Referencing Context in Lifecycle Methods
This section documents a legacy API. See the new API.
If contextTypes is defined within a component, the following lifecycle methods will receive an additional parameter, the context object:
As of React 16, componentDidUpdate no longer receives prevContext.
Referencing Context in Function Components
This section documents a legacy API. See the new API.
Function components are also able to reference context if contextTypes is defined as a property of the function. The following code shows a Button component written as a function component.
Updating Context
This section documents a legacy API. See the new API.
Don't do it.
React has an API to update context, but it is fundamentally broken and you should not use it.
The getChildContext function will be called when the state or props changes. In order to update data in the context, trigger a local state update with this.setState. This will trigger a new context and changes will be received by the children.
The problem is, if a context value provided by component changes, descendants that use that value won't update if an intermediate parent returns false from shouldComponentUpdate. This is totally out of control of the components using context, so there's basically no way to reliably update the context. This blog post has a good explanation of why this is a problem and how you might get around it.
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:
However, sometimes it's useful to insert a child into a different location in the DOM:
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.
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:
A Parent component in #app-root would be able to catch an uncaught, bubbling event from the sibling node #modal-root.
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.
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:
We include the entire listItems array inside a <ul> element, and render it to the DOM:
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.
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.
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:
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:
When you don't have stable IDs for rendered items, you may use the item index as a key as a last resort:
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.
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:
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:
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:
JSX allows embedding any expression in curly braces so we could inline the map() result:
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.
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:
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:
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:
To fix this, we will rename hello to Hello and use <Hello /> when referring to it:
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:
To fix this, we will assign the type to a capitalized variable first:
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:
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:
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:
When you pass a string literal, its value is HTML-unescaped. So these two JSX expressions are equivalent:
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:
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" syntax to pass the whole props object. These two components are equivalent:
You can also pick specific props that your component will consume while passing all other props using the spread syntax.
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:
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:
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:
JSX Children
You can provide more JSX elements as the children. This is useful for displaying nested components:
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:
A React component can also return an array of elements:
JavaScript Expressions as Children
You can pass any JavaScript expression as children, by enclosing it within {}. For example, these expressions are equivalent:
This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this renders an HTML list:
JavaScript expressions can be mixed with other types of children. This is often useful in lieu of string templates:
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:
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:
This can be useful to conditionally render React elements. This JSX renders the <Header /> component only if showHeader is true:
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:
To fix this, make sure that the expression before && is always boolean:
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:
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>
);
}
render() {
// React mounts a new div and renders the children into it
return (
<div>
{this.props.children}
</div>
);
}
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
);
}
// 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);
import React from 'react';
import CustomButton from './CustomButton';
function WarningButton() {
// return React.createElement(CustomButton, {color: 'red'}, null);
return <CustomButton color="red" />;
}
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" />;
}
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" />;
}
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" />;
}
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} />;
}
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} />;
}
<MyComponent foo={1 + 2 + 3 + 4} />
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>;
}
<div>
Here is a list:
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
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>,
];
}
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>
);
}
function Hello(props) {
return <div>Hello {props.addressee}!</div>;
}
// 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>
);
}
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.
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:
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:
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:
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
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.
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:
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:
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 rule as part of our 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
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
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
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:
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:
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:
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.
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.
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
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:
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 useRefdoesn'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 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:
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 neitheruseLayoutEffect 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 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":
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:
If you're familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.
There are two common kinds of side effects in React components: those that don't require cleanup, and those that do. Let's look at this distinction in more detail.
Effects Without Cleanup
Sometimes, we want to run some additional code after React has updated the DOM. Network requests, manual DOM mutations, and logging are common examples of effects that don't require a cleanup. We say that because we can run them and immediately forget about them. Let's compare how classes and Hooks let us express such side effects.
Example Using Classes
In React class components, the render method itself shouldn't cause side effects. It would be too early -- we typically want to perform our effects after React has updated the DOM.
This is why in React classes, we put side effects into componentDidMount and componentDidUpdate. Coming back to our example, here is a React counter class component that updates the document title right after React makes changes to the DOM:
Note how we have to duplicate the code between these two lifecycle methods in class.
This is because in many cases we want to perform the same side effect regardless of whether the component just mounted, or if it has been updated. Conceptually, we want it to happen after every render -- but React class components don't have a method like this. We could extract a separate method but we would still have to call it in two places.
Now let's see how we can do the same with the useEffect Hook.
Example Using Hooks
We've already seen this example at the top of this page, but let's take a closer look at it:
What does useEffect do? By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we'll refer to it as our "effect"), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.
Why is useEffect called inside a component? Placing useEffect inside the component lets us access the count state variable (or any props) right from the effect. We don't need a special API to read it -- it's already in the function scope. Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution.
Does useEffect run after every render? Yes! By default, it runs both after the first render and after every update. (We will later talk about how to customize this.) Instead of thinking in terms of "mounting" and "updating", you might find it easier to think that effects happen "after render". React guarantees the DOM has been updated by the time it runs the effects.
Detailed Explanation
Now that we know more about effects, these lines should make sense:
We declare the count state variable, and then we tell React we need to use an effect. We pass a function to the useEffect Hook. This function we pass is our effect. Inside our effect, we set the document title using the document.title browser API. We can read the latest count inside the effect because it's in the scope of our function. When React renders our component, it will remember the effect we used, and then run our effect after updating the DOM. This happens for every render, including the first one.
Experienced JavaScript developers might notice that the function passed to useEffect is going to be different on every render. This is intentional. In fact, this is what lets us read the count value from inside the effect without worrying about it getting stale. Every time we re-render, we schedule a different effect, replacing the previous one. In a way, this makes the effects behave more like a part of the render result -- each effect "belongs" to a particular render. We will see more clearly why this is useful later on this page.
Tip
Unlike componentDidMount or componentDidUpdate, effects scheduled with useEffect don't block the browser from updating the screen. This makes your app feel more responsive. The majority of effects don't need to happen synchronously. In the uncommon cases where they do (such as measuring the layout), there is a separate useLayoutEffect Hook with an API identical to useEffect.
Effects with Cleanup
Earlier, we looked at how to express side effects that don't require any cleanup. However, some effects do. For example, we might want to set up a subscription to some external data source. In that case, it is important to clean up so that we don't introduce a memory leak! Let's compare how we can do it with classes and with Hooks.
Example Using Classes
In a React class, you would typically set up a subscription in componentDidMount, and clean it up in componentWillUnmount. For example, let's say we have a ChatAPI module that lets us subscribe to a friend's online status. Here's how we might subscribe and display that status using a class:
Notice how componentDidMount and componentWillUnmount need to mirror each other. Lifecycle methods force us to split this logic even though conceptually code in both of them is related to the same effect.
Note
Eagle-eyed readers may notice that this example also needs a componentDidUpdate method to be fully correct. We'll ignore this for now but will come back to it in a later section of this page.
Example Using Hooks
Let's see how we could write this component with Hooks.
You might be thinking that we'd need a separate effect to perform the cleanup. But code for adding and removing a subscription is so tightly related that useEffect is designed to keep it together. If your effect returns a function, React will run it when it is time to clean up:
Why did we return a function from our effect? This is the optional cleanup mechanism for effects. Every effect may return a function that cleans up after it. This lets us keep the logic for adding and removing subscriptions close to each other. They're part of the same effect!
When exactly does React clean up an effect? React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time. We'll discuss why this helps avoid bugs and how to opt out of this behavior in case it creates performance issues later below.
Note
We don't have to return a named function from the effect. We called it cleanup here to clarify its purpose, but you could return an arrow function or call it something different.
Recap
We've learned that useEffect lets us express different kinds of side effects after a component renders. Some effects might require cleanup so they return a function:
Other effects might not have a cleanup phase, and don't return anything.
The Effect Hook unifies both use cases with a single API.
If you feel like you have a decent grasp on how the Effect Hook works, or if you feel overwhelmed, you can jump to the next page about Rules of Hooks now.
Tips for Using Effects
We'll continue this page with an in-depth look at some aspects of useEffect that experienced React users will likely be curious about. Don't feel obligated to dig into them now. You can always come back to this page to learn more details about the Effect Hook.
Tip: Use Multiple Effects to Separate Concerns
One of the problems we outlined in the Motivation for Hooks is that class lifecycle methods often contain unrelated logic, but related logic gets broken up into several methods. Here is a component that combines the counter and the friend status indicator logic from the previous examples:
Note how the logic that sets document.title is split between componentDidMount and componentDidUpdate. The subscription logic is also spread between componentDidMount and componentWillUnmount. And componentDidMount contains code for both tasks.
So, how can Hooks solve this problem? Just like you can use the State Hook more than once, you can also use several effects. This lets us separate unrelated logic into different effects:
Hooks let us split the code based on what it is doing rather than a lifecycle method name. React will apply every effect used by the component, in the order they were specified.
Explanation: Why Effects Run on Each Update
If you're used to classes, you might be wondering why the effect cleanup phase happens after every re-render, and not just once during unmounting. Let's look at a practical example to see why this design helps us create components with fewer bugs.
Earlier on this page, we introduced an example FriendStatus component that displays whether a friend is online or not. Our class reads friend.id from this.props, subscribes to the friend status after the component mounts, and unsubscribes during unmounting:
But what happens if the friend prop changes while the component is on the screen? Our component would continue displaying the online status of a different friend. This is a bug. We would also cause a memory leak or crash when unmounting since the unsubscribe call would use the wrong friend ID.
In a class component, we would need to add componentDidUpdate to handle this case:
Forgetting to handle componentDidUpdate properly is a common source of bugs in React applications.
Now consider the version of this component that uses Hooks:
It doesn't suffer from this bug. (But we also didn't make any changes to it.)
There is no special code for handling updates because useEffect handles them by default. It cleans up the previous effects before applying the next effects. To illustrate this, here is a sequence of subscribe and unsubscribe calls that this component could produce over time:
This behavior ensures consistency by default and prevents bugs that are common in class components due to missing update logic.
Tip: Optimizing Performance by Skipping Effects
In some cases, cleaning up or applying the effect after every render might create a performance problem. In class components, we can solve this by writing an extra comparison with prevProps or prevState inside componentDidUpdate:
This requirement is common enough that it is built into the useEffect Hook API. You can tell React to skip applying an effect if certain values haven't changed between re-renders. To do so, pass an array as an optional second argument to useEffect:
In the example above, we pass [count] as the second argument. What does this mean? If the count is 5, and then our component re-renders with count still equal to 5, React will compare [5] from the previous render and [5] from the next render. Because all items in the array are the same (5 === 5), React would skip the effect. That's our optimization.
When we render with count updated to 6, React will compare the items in the [5] array from the previous render to items in the [6] array from the next render. This time, React will re-apply the effect because 5 !== 6. If there are multiple items in the array, React will re-run the effect even if just one of them is different.
This also works for effects that have a cleanup phase:
In the future, the second argument might get added automatically by a build-time transformation.
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 changes 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 rule as part of our package. It warns when dependencies are specified incorrectly and suggests a fix.
Next Steps
Congratulations! This was a long page, but hopefully by the end most of your questions about effects were answered. You've learned both the State Hook and the Effect Hook, and there is a lot you can do with both of them combined. They cover most of the use cases for classes -- and where they don't, you might find the additional Hooks helpful.
We're also starting to see how Hooks solve problems outlined in Motivation. We've seen how effect cleanup avoids duplication in componentDidUpdate and componentWillUnmount, brings related code closer together, and helps us avoid bugs. We've also seen how we can separate effects by their purpose, which is something we couldn't do in classes at all.
At this point you might be questioning how Hooks work. How can React know which useState call corresponds to which state variable between re-renders? How does React "match up" previous and next effects on every update? On the next page we will learn about the Rules of Hooks -- they're essential to making Hooks work.
The PureRenderMixin mixin predates React.PureComponent. This reference doc is provided for legacy purposes, and you should consider using React.PureComponent instead.
If your React component's render function renders the same result given the same props and state, you can use this mixin for a performance boost in some cases.
Example:
var PureRenderMixin = require("react-addons-pure-render-mixin");
var createReactClass = require("create-react-class");
createReactClass({
mixins: [PureRenderMixin],
render: function () {
return <div className={this.props.className}>foo</div>;
},
});
Example using ES6 class syntax:
Under the hood, the mixin implements shouldComponentUpdate, in which it compares the current props and state with the next ones and returns false if the equalities pass.
Note:
This only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only mix into components which have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using to facilitate fast comparisons of nested data.
Furthermore, shouldComponentUpdate skips updates for the whole component subtree. Make sure all the children components are also "pure".
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:
Latest is for stable, semver React releases. It's what you get when you install React from npm. This is the channel you're already using today. Use this for all user-facing React applications.
tracks the main branch of the React source code repository. Think of these as release candidates for the next minor semver release. Use this for integration testing between React and third party projects.
includes experimental APIs and features that aren't available in the stable releases. These also track the main branch, but with additional feature flags turned on. Use this to try out upcoming features before they are released.
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 and the commit date, e.g. 0.0.0-68053d940-20210623 for Next and 0.0.0-experimental-68053d940-20210623 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 and .
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 main 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 and the commit date, e.g. 0.0.0-68053d940-20210623.
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:
Set up a cron job using your preferred continuous integration platform. Cron jobs are supported by both and .
In the cron job, update your React packages to the most recent React release in the Next channel, using next tag on npm. Using the npm cli:
Or yarn:
A project that uses this workflow is Next.js. (No pun intended! Seriously!) You can refer to their as an example.
Experimental Channel
Like Next, the Experimental channel is a prerelease channel that tracks the main 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 and the commit date, e.g. 0.0.0-experimental-68053d940-20210623.
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 .
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 for a comprehensive list of changes.
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.
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 are included in the page. You're on your own if you choose to take this path.
Reference
render()
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
hydrate()
Same as , 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()
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.
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()
Creates a portal. Portals provide a way to render children into a DOM node that exists outside the hierarchy of the DOM component.
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
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.
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.
Babel, JSX, and Build Steps
Do I need to use JSX with React?
No! Check out "React Without JSX" to learn more.
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:
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.
This page was about experimental features that aren't yet available in a stable release. It was aimed at early adopters and people who are curious.
Much of the information on this page is now outdated and exists only for archival purposes. Please refer to the React 18 Alpha announcement post for the up-to-date information.
Before React 18 is released, we will replace this page with stable documentation.
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:
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:
const [state, setState] = useState({});
setState((prevState) => {
// Object.assign would also work
return { ...prevState, ...updatedValues };
});
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;
}
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.
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.
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:
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:
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:
Create an ES6 class, with the same name, that extends React.Component.
Add a single empty method to it called render().
Move the body of the function into the render() method.
Replace props with this.props in the render() body.
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:
Replace this.props.date with this.state.date in the render() method:
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:
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:
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:
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:
Let's quickly recap what's going on and the order in which the methods are called:
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.
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.
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.
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.
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:
Instead, use setState():
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:
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:
We used an arrow function above, but it also works with regular functions:
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:
Then you can update them independently with separate setState() calls:
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:
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:
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:
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.
Replaces ReactDOM.render(<App />, rootNode) and enables Concurrent Mode.
For more information on Concurrent Mode, check out the Concurrent Mode documentation.
Suspense API
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> have 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 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
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
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.
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
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
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.
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
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.
Test Utilities
Importing
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 which is designed to enable and encourage writing tests that use your components as the end users do.
For React versions <= 16, the library makes it easy to assert, manipulate, and traverse your React Components' output.
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:
Here is how we can test it:
Don't forget that dispatching DOM events only works when the DOM container is added to the document. You can use a library like to reduce the boilerplate code.
The recipes document contains more details on how act() behaves, with examples and usage.
mockComponent()
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 instead.
isElement()
Returns true if element is any React element.
isElementOfType()
Returns true if element is a React element whose type is of a React componentClass.
isDOMComponent()
Returns true if instance is a DOM component (such as a <div> or <span>).
isCompositeComponent()
Returns true if instance is a user-defined component, such as a class or a function.
isCompositeComponentWithType()
Returns true if instance is a component whose type is of a React componentClass.
findAllInRenderedTree()
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()
Finds all DOM elements of components in the rendered tree that are DOM components with the class name matching className.
findRenderedDOMComponentWithClass()
Like 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()
Finds all DOM elements of components in the rendered tree that are DOM components with the tag name matching tagName.
findRenderedDOMComponentWithTag()
Like 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()
Finds all instances of components with type equal to componentClass.
findRenderedComponentWithType()
Same as 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()
Render a React element into a detached DOM node in the document. This function requires a DOM. It is effectively equivalent to:
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 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
Changing the value of an input field and then pressing ENTER.
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.
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.
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>
);
}
const SUSPENSE_CONFIG = { timeoutMs: 2000 };
import ReactTestUtils from "react-dom/test-utils"; // ES6
var ReactTestUtils = require("react-dom/test-utils"); // ES5 with npm