React Webpages
React Webpages
Context
Context provides a way to pass data through the component tree without having to pass props
down manually at every level.
In a typical React application, data is passed top-down (parent to child) via props, but this can
be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required
by many components within an application. Context provides a way to share values like these
between components without having to explicitly pass a prop through every level of the tree.
API
React.createContext
Context.Provider
Class.contextType
Context.Consumer
Examples
Dynamic Context
Caveats
Legacy API
Context is designed to share data that can be considered “global” for a tree of React
components, such as the current authenticated user, theme, or preferred language. For
example, in the code below we manually thread through a “theme” prop in order to style the
Button component:
function Toolbar(props) {
// The Toolbar component must take an extra "theme" prop
// and pass it to the ThemedButton. This can become painful
// if every single button in the app needs to know the theme
// because it would have to be passed through all components.
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}
Context is primarily used when some data needs to be accessible bymany components at
different nesting levels. Apply it sparingly because it makes component reuse more difficult.
If you only want to avoid passing some props through many levels,component
composition is often a simpler solution than context.
For example, consider a Page component that passes a user and avatarSize prop several
levels down so that deeply nested Link and Avatar components can read it:
It might feel redundant to pass down the user and avatarSize props through many levels if in
the end only the Avatar component really needs it. It’s also annoying that whenever the Avatar
component needs more props from the top, you have to add them at all the intermediate levels
too.
One way to solve this issuewithout context is to pass down the Avatar component itself so
that the intermediate components don’t need to know about the user or avatarSize props:
function Page(props) {
const user = props.user;
const userLink = (
<Link href={user.permalink}>
<Avatar user={user} size={props.avatarSize} />
</Link>
);
return <PageLayout userLink={userLink} />;
}
// Now, we have:
<Page user={user} avatarSize={avatarSize} />
// ... which renders ...
<PageLayout userLink={...} />
// ... which renders ...
<NavigationBar userLink={...} />
// ... which renders ...
{props.userLink}
With this change, only the top-most Page component needs to know about the Link and
Avatar components’ use of user and avatarSize .
This inversion of control can make your code cleaner in many cases by reducing the amount of
props you need to pass through your application and giving more control to the root
components. However, this isn’t the right choice in every case: moving more complexity higher
in the tree makes those higher-level components more complicated and forces the lower-level
components to be more flexible than you may want.
You’re not limited to a single child for a component. You may pass multiple children, or even
have multiple separate “slots” for children, as documented here:
function Page(props) {
const user = props.user;
const content = <Feed user={user} />;
const topBar = (
<NavigationBar>
<Link href={user.permalink}>
<Avatar user={user} size={props.avatarSize} />
</Link>
</NavigationBar>
);
return (
<PageLayout
topBar={topBar}
content={content}
/>
);
}
This pattern is sufficient for many cases when you need to decouple a child from its immediate
parents. You can take it even further with render props if the child needs to communicate with
the parent before rendering.
However, sometimes the same data needs to be accessible by many components in the tree,
and at different nesting levels. Context lets you “broadcast” such data, and changes to it, to all
components below. Common examples where using context might be simpler than the
alternatives include managing the current locale, theme, or a data cache.
API
React.createContext
Creates a Context object. When React renders a component that subscribes to this Context
object it will read the current context value from the closest matching Provider above it in the
tree.
The defaultValue argument is only used when a component does not have a matching
Provider above it in the tree. This can be helpful for testing components in isolation without
wrapping them. Note: passing undefined as a Provider value does not cause consuming
components to use defaultValue .
Context.Provider
Every Context object comes with a Provider React component that allows consuming
components to subscribe to context changes.
Accepts a value prop to be passed to consuming components that are descendants of this
Provider. One Provider can be connected to many consumers. Providers can be nested to
override values deeper within the tree.
All consumers that are descendants of a Provider will re-render whenever the Provider’s value
prop changes. The propagation from Provider to its descendant consumers is not subject to
the shouldComponentUpdate method, so the consumer is updated even when an ancestor
component bails out of the update.
Changes are determined by comparing the new and old values using the same algorithm as
Object.is .
Note
The way changes are determined can cause some issues when passing objects as value : see
Caveats.
Class.contextType
Note:
You can only subscribe to a single context using this API. If you need to read more than one
see Consuming Multiple Contexts.
If you are using the experimental public class fields syntax, you can use a static class field to
initialize your contextType .
Context.Consumer
<MyContext.Consumer>
{value => /* render something based on the context value */}
</MyContext.Consumer>
A React component that subscribes to context changes. This lets you subscribe to a context
within a function component.
Requires a function as a child. The function receives the current context value and returns a
React node. The value argument passed to the function will be equal to the value prop of the
closest Provider for this context above in the tree. If there is no Provider for this context above,
the value argument will be equal to the defaultValue that was passed to createContext() .
Note
For more information about the ‘function as a child’ pattern, seerender props.
Examples
Dynamic Context
theme-context.js
themed-button.js
app.js
this.toggleTheme = () => {
this.setState(state => ({
theme:
state.theme === themes.dark
? themes.light
: themes.dark,
}));
};
}
render() {
// The ThemedButton button inside the ThemeProvider
// uses the theme from state while the one outside uses
// the default dark theme
return (
<Page>
<ThemeContext.Provider value={this.state.theme}>
<Toolbar changeTheme={this.toggleTheme} />
</ThemeContext.Provider>
<Section>
<ThemedButton />
</Section>
</Page>
);
}
}
It is often necessary to update the context from a component that is nested somewhere deeply
in the component tree. In this case you can pass a function down through the context to allow
consumers to update the context:
theme-context.js
theme-toggler-button.js
function ThemeTogglerButton() {
// The Theme Toggler Button receives not only the theme
// but also a toggleTheme function from the context
return (
<ThemeContext.Consumer>
{({theme, toggleTheme}) => (
<button
onClick={toggleTheme}
style={{backgroundColor: theme.background}}>
Toggle Theme
</button>
)}
</ThemeContext.Consumer>
);
}
app.js
this.toggleTheme = () => {
this.setState(state => ({
theme:
state.theme === themes.dark
? themes.light
: themes.dark,
}));
};
render() {
// The entire state is passed to the provider
return (
<ThemeContext.Provider value={this.state}>
<Content />
</ThemeContext.Provider>
);
}
}
function Content() {
return (
<div>
<ThemeTogglerButton />
</div>
);
}
To keep context re-rendering fast, React needs to make each context consumer a separate
node in the tree.
function Layout() {
return (
<div>
<Sidebar />
<Content />
</div>
);
}
If two or more context values are often used together, you might want to consider creating your
own render prop component that provides both.
Caveats
Because context uses reference identity to determine when to re-render, there are some
gotchas that could trigger unintentional renders in consumers when a provider’s parent re-
renders. For example, the code below will re-render all consumers every time the Provider re-
renders because a new object is always created for value :
To get around this, lift the value into the parent’s state:
render() {
return (
<Provider value={this.state.value}>
<Toolbar />
</Provider>
);
}
}
Legacy API
Note
React previously shipped with an experimental context API. The old API will be supported in all
16.x releases, but applications using it should migrate to the new version. The legacy API will
be removed in a future major React version. Read the legacy context docs here.
D O C S C H A N N E L S C O M M U
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources
Docs Tutorial Blog Community
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
We’ll start learning about Hooks by comparing this code to an equivalent class example.
If you used classes in React before, this code should look familiar:
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
The state starts as { count: 0 } , and we increment state.count when the user clicks a button by
calling this.setState() . We’ll use snippets from this class throughout the page.
Note
You might be wondering why we’re using a counter here instead of a more realistic example.
This is to help us focus on the API while we’re still making our first steps with Hooks.
or this:
function Example(props) {
// You can use Hooks here!
return <div />;
}
You might have previously known these as “stateless components”. We’re now introducing the
ability to use React state from these, so we prefer the name “function components”.
Hooks don’t work inside classes. But you can use them instead of writing classes.
What’s a Hook?
Our new example starts by importing the useState Hook from React:
function Example() {
// ...
}
What is a Hook? A Hook is a special function that lets you “hook into” React features. For
example, useState is a Hook that lets you add React state to function components. We’ll learn
other Hooks later.
When would I use a Hook? If you write a function component and realize you need to add
some state to it, previously you had to convert it to a class. Now you can use a Hook inside the
existing function component. We’re going to do that right now!
Note:
There are some special rules about where you can and can’t use Hooks within a component.
We’ll learn them in Rules of Hooks.
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
What does calling useState do? It declares a “state variable”. Our variable is called count but
we could call it anything else, like banana . This is a way to “preserve” some values between
the function calls — useState is a new way to use the exact same capabilities that this.state
provides in a class. Normally, variables “disappear” when the function exits but state variables
are preserved by React.
What do we pass to useState as an argument? The only argument to the useState() Hook
is the initial state. Unlike with classes, the state doesn’t have to be an object. We can keep a
number or a string if that’s all we need. In our example, we just want a number for how many
times the user clicked, so pass 0 as initial state for our variable. (If we wanted to store two
different values in state, we would call useState() twice.)
What does useState return? It returns a pair of values: the current state and a function that
updates it. This is why we write const [count, setCount] = useState() . This is similar to
this.state.count and this.setState in a class, except you get them in a pair. If you’re not familiar
with the syntax we used, we’ll come back to it at the bottom of this page.
Now that we know what the useState Hook does, our example should make more sense:
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
We declare a state variable called count , and set it to 0 . React will remember its current value
between re-renders, and provide the most recent one to our function. If we want to update the
current count , we can call setCount .
Note
You might be wondering: why is useState not named createState instead?
“Create” wouldn’t be quite accurate because the state is only created the first time our
component renders. During the next renders, useState gives us the current state. Otherwise it
wouldn’t be “state” at all! There’s also a reason why Hook names always start with use . We’ll
learn why later in the Rules of Hooks.
Reading State
Updating State
In a function, we already have setCount and count as variables so we don’t need this :
Recap
Let’s now recap what we learned line by line and check our understanding.
Line 1: We import the useState Hook from React. It lets us keep local state in a function component.
Line 4: Inside the Example component, we declare a new state variable by calling the useState Hook. It returns a pair of values, to which we give names. We’re calling our variablecount because it
holds the number of button clicks. We initialize it to zero by passing 0 as the only useState argument. The second returned item is itself a function. It lets us update the count so we’ll name it setCount .
Line 9: When the user clicks, we call setCount with a new value. React will then re-render the Example component, passing the new count value to it.
This might seem like a lot to take in at first. Don’t rush it! If you’re lost in the explanation, look
at the code above again and try to read it from top to bottom. We promise that once you try to
“forget” how state works in classes, and look at this code with fresh eyes, it will make sense.
You might have noticed the square brackets when we declare a state variable:
The names on the left aren’t a part of the React API. You can name your own state variables:
This JavaScript syntax is called “array destructuring”. It means that we’re making two new
variables fruit and setFruit , where fruit is set to the first value returned by useState , and
setFruit is the second. It is equivalent to this code:
When we declare a state variable with useState , it returns a pair — an array with two items.
The first item is the current value, and the second is a function that lets us update it. Using [0]
and [1] to access them is a bit confusing because they have a specific meaning. This is why
we use array destructuring instead.
Note
You might be curious how React knows which component useState corresponds to since
we’re not passing anything like this back to React. We’ll answer this question and many others
in the FAQ section.
Declaring state variables as a pair of [something, setSomething] is also handy because it lets us
give different names to different state variables if we want to use more than one:
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
In the above component, we have age , fruit , and todos as local variables, and we can update
them individually:
function handleOrangeClick() {
// Similar to this.setState({ fruit: 'orange' })
setFruit('orange');
}
You don’t have to use many state variables. State variables can hold objects and arrays just
fine, so you can still group related data together. However, unlike this.setState in a class,
updating a state variable always replaces it instead of merging it.
Next Steps
On this page we’ve learned about one of the Hooks provided by React, called useState . We’re
also sometimes going to refer to it as the “State Hook”. It lets us add local state to React
function components — which we did for the first time ever!
We also learned a little bit more about what Hooks are. Hooks are functions that let you “hook
into” React features from function components. Their names always start with use , and there
are more Hooks we haven’t seen yet.
Now let’s continue by learning the next Hook: useEffect. It lets you perform side effects in
components, and is similar to lifecycle methods in classes.
D O C S C H A N N E L S C O M M U
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources
Docs Tutorial Blog Community
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
We’ll start learning about Hooks by comparing this code to an equivalent class example.
If you used classes in React before, this code should look familiar:
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
The state starts as { count: 0 } , and we increment state.count when the user clicks a button by
calling this.setState() . We’ll use snippets from this class throughout the page.
Note
You might be wondering why we’re using a counter here instead of a more realistic example.
This is to help us focus on the API while we’re still making our first steps with Hooks.
or this:
function Example(props) {
// You can use Hooks here!
return <div />;
}
You might have previously known these as “stateless components”. We’re now introducing the
ability to use React state from these, so we prefer the name “function components”.
Hooks don’t work inside classes. But you can use them instead of writing classes.
What’s a Hook?
Our new example starts by importing the useState Hook from React:
function Example() {
// ...
}
What is a Hook? A Hook is a special function that lets you “hook into” React features. For
example, useState is a Hook that lets you add React state to function components. We’ll learn
other Hooks later.
When would I use a Hook? If you write a function component and realize you need to add
some state to it, previously you had to convert it to a class. Now you can use a Hook inside the
existing function component. We’re going to do that right now!
Note:
There are some special rules about where you can and can’t use Hooks within a component.
We’ll learn them in Rules of Hooks.
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
What does calling useState do? It declares a “state variable”. Our variable is called count but
we could call it anything else, like banana . This is a way to “preserve” some values between
the function calls — useState is a new way to use the exact same capabilities that this.state
provides in a class. Normally, variables “disappear” when the function exits but state variables
are preserved by React.
What do we pass to useState as an argument? The only argument to the useState() Hook
is the initial state. Unlike with classes, the state doesn’t have to be an object. We can keep a
number or a string if that’s all we need. In our example, we just want a number for how many
times the user clicked, so pass 0 as initial state for our variable. (If we wanted to store two
different values in state, we would call useState() twice.)
What does useState return? It returns a pair of values: the current state and a function that
updates it. This is why we write const [count, setCount] = useState() . This is similar to
this.state.count and this.setState in a class, except you get them in a pair. If you’re not familiar
with the syntax we used, we’ll come back to it at the bottom of this page.
Now that we know what the useState Hook does, our example should make more sense:
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
We declare a state variable called count , and set it to 0 . React will remember its current value
between re-renders, and provide the most recent one to our function. If we want to update the
current count , we can call setCount .
Note
You might be wondering: why is useState not named createState instead?
“Create” wouldn’t be quite accurate because the state is only created the first time our
component renders. During the next renders, useState gives us the current state. Otherwise it
wouldn’t be “state” at all! There’s also a reason why Hook names always start with use . We’ll
learn why later in the Rules of Hooks.
Reading State
Updating State
In a function, we already have setCount and count as variables so we don’t need this :
Recap
Let’s now recap what we learned line by line and check our understanding.
Line 1: We import the useState Hook from React. It lets us keep local state in a function component.
Line 4: Inside the Example component, we declare a new state variable by calling the useState Hook. It returns a pair of values, to which we give names. We’re calling our variablecount because it
holds the number of button clicks. We initialize it to zero by passing 0 as the only useState argument. The second returned item is itself a function. It lets us update the count so we’ll name it setCount .
Line 9: When the user clicks, we call setCount with a new value. React will then re-render the Example component, passing the new count value to it.
This might seem like a lot to take in at first. Don’t rush it! If you’re lost in the explanation, look
at the code above again and try to read it from top to bottom. We promise that once you try to
“forget” how state works in classes, and look at this code with fresh eyes, it will make sense.
You might have noticed the square brackets when we declare a state variable:
The names on the left aren’t a part of the React API. You can name your own state variables:
This JavaScript syntax is called “array destructuring”. It means that we’re making two new
variables fruit and setFruit , where fruit is set to the first value returned by useState , and
setFruit is the second. It is equivalent to this code:
When we declare a state variable with useState , it returns a pair — an array with two items.
The first item is the current value, and the second is a function that lets us update it. Using [0]
and [1] to access them is a bit confusing because they have a specific meaning. This is why
we use array destructuring instead.
Note
You might be curious how React knows which component useState corresponds to since
we’re not passing anything like this back to React. We’ll answer this question and many others
in the FAQ section.
Declaring state variables as a pair of [something, setSomething] is also handy because it lets us
give different names to different state variables if we want to use more than one:
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
In the above component, we have age , fruit , and todos as local variables, and we can update
them individually:
function handleOrangeClick() {
// Similar to this.setState({ fruit: 'orange' })
setFruit('orange');
}
You don’t have to use many state variables. State variables can hold objects and arrays just
fine, so you can still group related data together. However, unlike this.setState in a class,
updating a state variable always replaces it instead of merging it.
Next Steps
On this page we’ve learned about one of the Hooks provided by React, called useState . We’re
also sometimes going to refer to it as the “State Hook”. It lets us add local state to React
function components — which we did for the first time ever!
We also learned a little bit more about what Hooks are. Hooks are functions that let you “hook
into” React features from function components. Their names always start with use , and there
are more Hooks we haven’t seen yet.
Now let’s continue by learning the next Hook: useEffect. It lets you perform side effects in
components, and is similar to lifecycle methods in classes.
D O C S C H A N N E L S C O M M U
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources
Docs Tutorial Blog Community
The Effect Hook lets you perform side effects in function components:
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
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.
Tip
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.
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.
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:
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
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.
We’ve already seen this example at the top of this page, but let’s take a closer look at it:
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
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 renderand
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:
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
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 .
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.
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:
componentDidMount() {
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
handleStatusChange(status) {
this.setState({
isOnline: status.isOnline
});
}
render() {
if (this.state.isOnline === null) {
return 'Loading...';
}
return this.state.isOnline ? 'Online' : 'Offline';
}
}
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.
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:
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
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:
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
Other effects might not have a cleanup phase, and don’t return anything.
useEffect(() => {
document.title = `You clicked ${count} times`;
});
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.
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.
One of the problems we outlined in theMotivation 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:
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
handleStatusChange(status) {
this.setState({
isOnline: status.isOnline
});
}
// ...
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 likeyou can use the State Hook more than once,
you can also use several effects. This lets us separate unrelated logic into different effects:
function FriendStatusWithCounter(props) {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
// ...
}
Hooks lets 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.
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:
componentDidMount() {
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
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.
componentDidMount() {
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentDidUpdate(prevProps) {
// Unsubscribe from the previous friend.id
ChatAPI.unsubscribeFromFriendStatus(
prevProps.friend.id,
this.handleStatusChange
);
// Subscribe to the next friend.id
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
function FriendStatus(props) {
// ...
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
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:
// Unmount
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // Clean up last effect
This behavior ensures consistency by default and prevents bugs that are common in class
components due to missing update logic.
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 :
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
document.title = `You clicked ${this.state.count} times`;
}
}
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 :
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
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.
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
}, [props.friend.id]); // Only re-subscribe if props.friend.id changes
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 any values from the outer scope
that change over time and that are used by the effect. Otherwise, your code will reference
stale values from previous renders. We’ll also discuss other optimization options in the Hooks
API reference.
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 inputs array always works. While passing [] is closer to the
familiar componentDidMount and componentWillUnmount mental model, we suggest not making
it a habit because it often leads to bugs, as discussed above. Don’t forget that React defers
running useEffect until after the browser has painted, so doing extra work is less of a problem.
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 inMotivation. 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 theRules
of Hooks — they’re essential to making Hooks work.
D O C S C H A N N E L S C O M M U
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources
Docs Tutorial Blog Community
Rules of Hooks
Hooks are a new addition in React 16.8. They let you use state and other React features
without writing a class.
Hooks are JavaScript functions, but you need to follow two rules when using them. We provide
a linter plugin to enforce these rules automatically:
Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks
at the top level of your React function. By following this rule, you ensure that Hooks are called
in the same order each time a component renders. That’s what allows React to correctly
preserve the state of Hooks between multiple useState and useEffect calls. (If you’re curious,
we’ll explain this in depth below.)
Don’t call Hooks from regular JavaScript functions. Instead, you can:
Call Hooks from custom Hooks (we’ll learn about them on the next page).
By following this rule, you ensure that all stateful logic in a component is clearly visible from its
source code.
ESLint Plugin
We released an ESLint plugin called eslint-plugin-react-hooks that enforces these two rules.
You can add this plugin to your project if you’d like to try it:
In the future, we intend to include this plugin by default into Create React App and similar
toolkits.
You can skip to the next page explaining how to writeyour own Hooks now. On this
page, we’ll continue by explaining the reasoning behind these rules.
Explanation
As we learned earlier, we can use multiple State or Effect Hooks in a single component:
function Form() {
// 1. Use the name state variable
const [name, setName] = useState('Mary');
// ...
}
So how does React know which state corresponds to which useState call? The answer is that
React relies on the order in which Hooks are called. Our example works because the order
of the Hook calls is the same on every render:
// ------------
// First render
// ------------
useState('Mary') // 1. Initialize the name state variable with 'Mary'
useEffect(persistForm) // 2. Add an effect for persisting the form
useState('Poppins') // 3. Initialize the surname state variable with 'Poppins'
useEffect(updateTitle) // 4. Add an effect for updating the title
// -------------
// Second render
// -------------
useState('Mary') // 1. Read the name state variable (argument is ignored)
useEffect(persistForm) // 2. Replace the effect for persisting the form
useState('Poppins') // 3. Read the surname state variable (argument is ignored)
useEffect(updateTitle) // 4. Replace the effect for updating the title
// ...
As long as the order of the Hook calls is the same between renders, React can associate
some local state with each of them. But what happens if we put a Hook call (for example, the
persistForm effect) inside a condition?
The name !== '' condition is true on the first render, so we run this Hook. However, on the next
render the user might clear the form, making the condition false . Now that we skip this Hook
during rendering, the order of the Hook calls becomes different:
React wouldn’t know what to return for the second useState Hook call. React expected that the
second Hook call in this component corresponds to the persistForm effect, just like during the
previous render, but it doesn’t anymore. From that point, every next Hook call after the one we
skipped would also shift by one, leading to bugs.
This is why Hooks must be called on the top level of our components.If we want to run
an effect conditionally, we can put that condition inside our Hook:
useEffect(function persistForm() {
// We're not breaking the first rule anymore
if (name !== '') {
localStorage.setItem('formData', name);
}
});
Note that you don’t need to worry about this problem if you use theprovided lint rule.
But now you also know why Hooks work this way, and which issues the rule is preventing.
Next Steps
Finally, we’re ready to learn about writing your own Hooks! Custom Hooks let you combine
Hooks provided by React into your own abstractions, and reuse common stateful logic between
different components.
D O C S C H A N N E L S C O M M U
D O C S C H A N N E L S C O M M U
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources
Docs Tutorial Blog Community
Building your own Hooks lets you extract component logic into reusable functions.
When we were learning about using the Effect Hook, we saw this component from a chat
application that displays a message indicating whether a friend is online or offline:
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
Now let’s say that our chat application also has a contact list, and we want to render names of
online users with a green color. We could copy and paste similar logic above into our
FriendListItem component but it wouldn’t be ideal:
function FriendListItem(props) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
Instead, we’d like to share this logic between FriendStatus and FriendListItem .
Traditionally in React, we’ve had two popular ways to share stateful logic between
components: render props and higher-order components. We will now look at how Hooks solve
many of the same problems without forcing you to add more components to the tree.
When we want to share logic between two JavaScript functions, we extract it to a third function.
Both components and Hooks are functions, so this works for them too!
A custom Hook is a JavaScript function whose name starts with ”use” and that may call
other Hooks. For example, useFriendStatus below is our first custom Hook:
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
There’s nothing new inside of it — the logic is copied from the components above. Just like in a
component, make sure to only call other Hooks unconditionally at the top level of your custom
Hook.
Unlike a React component, a custom Hook doesn’t need to have a specific signature. We can
decide what it takes as arguments, and what, if anything, it should return. In other words, it’s
just like a normal function. Its name should always start with use so that you can tell at a
glance that the rules of Hooks apply to it.
The purpose of our useFriendStatus Hook is to subscribe us to a friend’s status. This is why it
takes friendID as an argument, and returns whether this friend is online:
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
// ...
return isOnline;
}
In the beginning, our stated goal was to remove the duplicated logic from theFriendStatus and
FriendListItem components. Both of them want to know whether a friend is online.
Now that we’ve extracted this logic to a useFriendStatus hook, we can just use it:
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
Is this code equivalent to the original examples? Yes, it works in exactly the same way. If
you look closely, you’ll notice we didn’t make any changes to the behavior. All we did was to
extract some common code between two functions into a separate function. Custom Hooks
are a convention that naturally follows from the design of Hooks, rather than a React
feature.
Do I have to name my custom Hooks starting with “use”? Please do. This convention is
very important. Without it, we wouldn’t be able to automatically check for violations of rules of
Hooks because we couldn’t tell if a certain function contains calls to Hooks inside of it.
Do two components using the same Hook share state? No. Custom Hooks are a
mechanism to reuse stateful logic (such as setting up a subscription and remembering the
current value), but every time you use a custom Hook, all state and effects inside of it are fully
isolated.
How does a custom Hook get isolated state? Each call to a Hook gets isolated state.
Because we call useFriendStatus directly, from React’s point of view our component just calls
useState and useEffect . And as we learned earlier, we can call useState and useEffect many
times in one component, and they will be completely independent.
Tip: Pass Information Between Hooks
To illustrate this, we’ll use another component from our hypothetical chat example. This is a
chat message recipient picker that displays whether the currently selected friend is online:
const friendList = [
{ id: 1, name: 'Phoebe' },
{ id: 2, name: 'Rachel' },
{ id: 3, name: 'Ross' },
];
function ChatRecipientPicker() {
const [recipientID, setRecipientID] = useState(1);
const isRecipientOnline = useFriendStatus(recipientID);
return (
<>
<Circle color={isRecipientOnline ? 'green' : 'red'} />
<select
value={recipientID}
onChange={e => setRecipientID(Number(e.target.value))}
>
{friendList.map(friend => (
<option key={friend.id} value={friend.id}>
{friend.name}
</option>
))}
</select>
</>
);
}
We keep the currently chosen friend ID in the recipientID state variable, and update it if the
user chooses a different friend in the <select> picker.
Because the useState Hook call gives us the latest value of the recipientID state variable, we
can pass it to our custom useFriendStatus Hook as an argument:
This lets us know whether the currently selected friend is online. If we pick a different friend and
update the recipientID state variable, our useFriendStatus Hook will unsubscribe from the
previously selected friend, and subscribe to the status of the newly selected one.
useYourImagination()
Custom Hooks offer the flexibility of sharing logic that wasn’t possible in React components
before. You can write custom Hooks that cover a wide range of use cases like form handling,
animation, declarative subscriptions, timers, and probably many more we haven’t considered.
What’s more, you can build Hooks that are just as easy to use as React’s built-in features.
Try to resist adding abstraction too early. Now that function components can do more, it’s likely
that the average function component in your codebase will become longer. This is normal —
don’t feel like you have to immediately split it into Hooks. But we also encourage you to start
spotting cases where a custom Hook could hide complex logic behind a simple interface, or
help untangle a messy component.
For example, maybe you have a complex component that contains a lot of local state that is
managed in an ad-hoc way. useState doesn’t make centralizing the update logic any easier so
might you prefer to write it as a Redux reducer:
Reducers are very convenient to test in isolation, and scale to express complex update logic.
You can further break them apart into smaller reducers if necessary. However, you might also
enjoy the benefits of using React local state, or might not want to install another library.
So what if we could write a useReducer Hook that lets us manage the local state of our
component with a reducer? A simplified version of it might look like this:
function dispatch(action) {
const nextState = reducer(state, action);
setState(nextState);
}
Now we could use it in our component, and let the reducer drive its state management:
function Todos() {
const [todos, dispatch] = useReducer(todosReducer, []);
function handleAddClick(text) {
dispatch({ type: 'add', text });
}
// ...
}
The need to manage local state with a reducer in a complex component is common enough
that we’ve built the useReducer Hook right into React. You’ll find it together with other built-in
Hooks in the Hooks API reference.
D O C S C H A N N E L S C O M M U
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources
Docs Tutorial Blog Community
This page describes the APIs for the built-in Hooks in React.
If you’re new to Hooks, you might want to check outthe overview first. You may also find
useful information in the frequently asked questions section.
Basic Hooks
useState
useEffect
useContext
Additional Hooks
useReducer
useCallback
useMemo
useRef
useImperativeHandle
useLayoutEffect
useDebugValue
Basic Hooks
useState
During the initial render, the returned state (state ) is the same as the value passed as the first
argument ( initialState ).
The setState function is used to update the state. It accepts a new state value and enqueues a
re-render of the component.
setState(newState);
During subsequent re-renders, the first value returned by useState will always be the most
recent state after applying updates.
Functional updates
If the new state is computed using the previous state, you can pass a function tosetState . The
function will receive the previous value, and return an updated value. Here’s an example of a
counter component that uses both forms of setState :
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
</>
);
}
The ”+” and ”-” buttons use the functional form, because the updated value is based on the
previous value. But the “Reset” button uses the normal form, because it always sets the count
back to 0.
Note
Unlike the setState method found in class components, useState does not automatically
merge update objects. You can replicate this behavior by combining the function updater form
with object spread syntax:
setState(prevState => {
// Object.assign would also work
return {...prevState, ...updatedValues};
});
Another option is useReducer , which is more suited for managing state objects that contain
multiple sub-values.
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:
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.)
useEffect
useEffect(didUpdate);
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main
body of a function component (referred to as React’s render phase). Doing so will lead to
confusing bugs and inconsistencies in the UI.
Instead, use useEffect . The function passed to useEffect will run after the render is committed
to the screen. Think of effects as an escape hatch from React’s purely functional world into the
imperative world.
By default, effects run after every completed render, but you can choose to fire itonly when
certain values have changed.
Cleaning up an effect
Often, effects create resources that need to be cleaned up before the component leaves the
screen, such as a subscription or timer ID. To do this, the function passed to useEffect may
return a clean-up function. For example, to create a subscription:
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
// Clean up the subscription
subscription.unsubscribe();
};
});
The clean-up function runs before the component is removed from the UI to prevent memory
leaks. Additionally, if a component renders multiple times (as they typically do), the previous
effect is cleaned up before executing the next effect. In our example, this means a new
subscription is created on every update. To avoid firing an effect on every update, refer to the
next section.
Timing of effects
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.
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 inputs 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 props
has changed.
To implement this, pass a second argument to useEffect that is the array of values that the
effect depends on. Our updated example now looks like this:
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
Passing in an empty array [] of inputs tells React that your effect doesn’t depend on any
values from the component, so that effect would run only on mount and clean up on unmount;
it won’t run on updates.
Note
The array of inputs 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 inputs 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, as given by the nearest context provider for the given context.
When the provider updates, this Hook will trigger a rerender with the latest context value.
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:
function Counter({initialState}) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}
There’s two different ways to initialize useReducer state. You may choose either one
depending on the use case. The simplest way 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:
function init(initialCount) {
return {count: initialCount};
}
function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}>
Reset
</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}
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.)
useCallback
Pass an inline callback and an array of inputs. useCallback will return a memoized version of
the callback that only changes if one of the inputs has changed. This is useful when passing
callbacks to optimized child components that rely on reference equality to prevent unnecessary
renders (e.g. shouldComponentUpdate ).
Note
The array of inputs 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
inputs array. In the future, a sufficiently advanced compiler could create this array
automatically.
useMemo
Pass a “create” function and an array of inputs. useMemo will only recompute the memoized
value when one of the inputs 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 whenever a new function instance is
passed as the first argument. (With an inline function, on every render.)
Note
The array of inputs 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
inputs array. In the future, a sufficiently advanced compiler could create this array
automatically.
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.
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
Note that 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.
useImperativeHandle
In this example, a parent component that renders <FancyInput ref={fancyInputRef} /> would be
able to call fancyInputRef.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, useLayoutEffect fires in the same phase as
componentDidMount and componentDidUpdate , so if you’re unsure of which effect Hook to use,
it’s probably the least risky.
useDebugValue
useDebugValue(value)
useDebugValue can be used to display a label for custom hooks in React DevTools.
For example, consider the useFriendStatus custom Hook described in “Building Your Own
Hooks”:
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
// ...
return isOnline;
}
Tip
We don’t recommend adding debug values to every custom Hook. It’s most valuable for
custom Hooks that are part of shared libraries.
In some cases formatting a value for display might be an expensive operation. It’s also
unnecessary unless a Hook is actually inspected.
For example a custom Hook that returned a Date value could avoid calling the toDateString
function unnecessarily by passing the following formatter:
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources
Docs Tutorial Blog Community
Hooks
FAQ
Hooks are a new addition in React 16.8. They let you use state and other React features
without writing a class.
Adoption Strategy
What do Hooks mean for popular APIs like Redux connect() and React Router?
Performance Optimizations
Adoption Strategy
Starting with 16.8.0, React includes a stable implementation of React Hooks for:
React DOM
Note that to enable Hooks, all React packages need to be 16.8.0 or higher. Hooks won’t
work if you forget to update, for example, React DOM.
React Native will fully support Hooks in its next stable release.
No. There are no plans to remove classes from React — we all need to keep shipping products
and can’t afford rewrites. We recommend trying Hooks in new code.
What can I do with Hooks that I couldn’t with classes?
Hooks offer a powerful and expressive new way to reuse functionality between components.
“Building Your Own Hooks” provides a glimpse of what’s possible.This article by a React core
team member dives deeper into the new capabilities unlocked by Hooks.
Hooks are a more direct way to use the React features you already know — such as state,
lifecycle, context, and refs. They don’t fundamentally change how React works, and your
knowledge of components, props, and top-down data flow is just as relevant.
Hooks do have a learning curve of their own. If there’s something missing in this
documentation, raise an issue and we’ll try to help.
When you’re ready, we’d encourage you to start trying Hooks in new components you write.
Make sure everyone on your team is on board with using them and familiar with this
documentation. We don’t recommend rewriting your existing classes to Hooks unless you
planned to rewrite them anyway (e.g. to fix bugs).
You can’t use Hooks inside of a class component, but you can definitely mix classes and
function components with Hooks in a single tree. Whether a component is a class or a function
that uses Hooks is an implementation detail of that component. In the longer term, we expect
Hooks to be the primary way people write React components.
Our goal is for Hooks to cover all use cases for classes as soon as possible. There are no
Hook equivalents to the uncommon getSnapshotBeforeUpdate and componentDidCatch
lifecycles yet, but we plan to add them soon.
It is an early time for Hooks, and some third-party libraries might not be compatible with Hooks
at the moment.
Often, render props and higher-order components render only a single child. We think Hooks
are a simpler way to serve this use case. There is still a place for both patterns (for example, a
virtual scroller component might have a renderItem prop, or a visual container component
might have its own DOM structure). But in most cases, Hooks will be sufficient and can help
reduce nesting in your tree.
What do Hooks mean for popular APIs like Redux connect() and React Router?
You can continue to use the exact same APIs as you always have; they’ll continue to work.
In the future, new versions of these libraries might also export custom Hooks such as
useRedux() or useRouter() that let you use the same features without needing wrapper
components.
Hooks were designed with static typing in mind. Because they’re functions, they are easier to
type correctly than patterns like higher-order components. The latest Flow and TypeScript
React definitions include support for React Hooks.
Importantly, custom Hooks give you the power to constrain React API if you’d like to type them
more strictly in some way. React gives you the primitives, but you can combine them in
different ways than what we provide out of the box.
From React’s point of view, a component using Hooks is just a regular component. If your
testing solution doesn’t rely on React internals, testing components with Hooks shouldn’t be
different from how you normally test components.
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
We’ll test it using React DOM. To make sure that the behavior matches what happens in the
browser, we’ll wrap the code rendering and updating it into ReactTestUtils.act() calls:
let container;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
The calls to act() will also flush the effects inside of them.
If you need to test a custom Hook, you can do so by creating a component in your test, and
using your Hook from it. Then you can test the component you wrote.
We provide an ESLint plugin that enforces rules of Hooks to avoid bugs. It assumes that any
function starting with ” use ” and a capital letter right after it is a Hook. We recognize this
heuristic isn’t perfect and there may be some false positives, but without an ecosystem-wide
convention there is just no way to make Hooks work well — and longer names will discourage
people from either adopting Hooks or following the convention.
Calls to Hooks are either inside a PascalCase function (assumed to be a component) or another useSomething function (assumed to be a custom Hook).
There are a few more heuristics, and they might change over time as we fine-tune the rule to
balance finding bugs with avoiding false positives.
constructor : Function components don’t need a constructor. You can initialize the state in the
useState call. If computing the initial state is expensive, you can pass a function to useState .
Yes! The useRef() Hook isn’t just for DOM refs. The “ref” object is a generic container whose
current property is mutable and can hold any value, similar to an instance property on a class.
function Timer() {
const intervalRef = useRef();
useEffect(() => {
const id = setInterval(() => {
// ...
});
intervalRef.current = id;
return () => {
clearInterval(intervalRef.current);
};
});
// ...
}
If we just wanted to set an interval, we wouldn’t need the ref (id could be local to the effect),
but it’s useful if we want to clear the interval from an event handler:
// ...
function handleCancelClick() {
clearInterval(intervalRef.current);
}
// ...
Conceptually, you can think of refs as similar to instance variables in a class. Unless you’re
doing lazy initialization, avoid setting refs during rendering — this can lead to surprising
behavior. Instead, typically you want to modify refs in event handlers and effects.
If you’re coming from classes, you might be tempted to always call useState() once and put all
state into a single object. You can do it if you’d like. Here is an example of a component that
follows the mouse movement. We keep its position and size in the local state:
function Box() {
const [state, setState] = useState({ left: 0, top: 0, width: 100, height: 100 });
// ...
}
Now let’s say we want to write some logic that changes left and top when the user moves
their mouse. Note how we have to merge these fields into the previous state object manually:
// ...
useEffect(() => {
function handleWindowMouseMove(e) {
// Spreading "...state" ensures we don't "lose" width and height
setState(state => ({ ...state, left: e.pageX, top: e.pageY }));
}
// Note: this implementation is a bit simplified
window.addEventListener('mousemove', handleWindowMouseMove);
return () => window.removeEventListener('mousemove', handleWindowMouseMove);
}, []);
// ...
This is because when we update a state variable, wereplace its value. This is different from
this.setState in a class, which merges the updated fields into the object.
If you miss automatic merging, you can write a custom useLegacyState Hook that merges
object state updates. However, instead we recommend to split state into multiple state
variables based on which values tend to change together.
For example, we could split our component state into position and size objects, and always
replace the position with no need for merging:
function Box() {
const [position, setPosition] = useState({ left: 0, top: 0 });
const [size, setSize] = useState({ width: 100, height: 100 });
useEffect(() => {
function handleWindowMouseMove(e) {
setPosition({ left: e.pageX, top: e.pageY });
}
// ...
Separating independent state variables also has another benefit. It makes it easy to later
extract some related logic into a custom Hook, for example:
function Box() {
const position = useWindowPosition();
const [size, setSize] = useState({ width: 100, height: 100 });
// ...
}
function useWindowPosition() {
const [position, setPosition] = useState({ left: 0, top: 0 });
useEffect(() => {
// ...
}, []);
return position;
}
Note how we were able to move the useState call for the position state variable and the
related effect into a custom Hook without changing their code. If all state was in a single object,
extracting it would be more difficult.
Both putting all state in a single useState call, and having a useState call per each field can
work. Components tend to be most readable when you find a balance between these two
extremes, and group related state into a few independent state variables. If the state logic
becomes complex, we recommend managing it with a reducer or a custom Hook.
This is a rare use case. If you need it, you canuse a mutable ref to manually store a boolean
value corresponding to whether you are on the first or a subsequent render, then check that
flag in your effect. (If you find yourself doing this often, you could create a custom Hook for it.)
function Counter() {
const [count, setCount] = useState(0);
This might be a bit convoluted but you can extract it into a custom Hook:
function Counter() {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
return <h1>Now: {count}, before: {prevCount}</h1>;
}
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
Note how this would work for props, state, or any other calculated value.
function Counter() {
const [count, setCount] = useState(0);
It’s possible that in the future React will provide a usePrevious Hook out of the box since it’s a
relatively common use case.
While you probably don’t need it, in rare cases that you do (such as implementing a
<Transition> component), you can update the state right during rendering. React will re-run the
component with updated state immediately after exiting the first render so it wouldn’t be
expensive.
Here, we store the previous value of the row prop in a state variable so that we can compare:
function ScrollView({row}) {
let [isScrollingDown, setIsScrollingDown] = useState(false);
let [prevRow, setPrevRow] = useState(null);
This might look strange at first, but an update during rendering is exactly what
getDerivedStateFromProps has always been like conceptually.
Both useState and useReducer Hooks bail out of updates if the next value is the same as the
previous one. Mutating state in place and calling setState will not cause a re-render.
Normally, you shouldn’t mutate local state in React. However, as an escape hatch, you can use
an incrementing counter to force a re-render even if the state has not changed:
function handleClick() {
forceUpdate();
}
While you shouldn’t need this often, you may expose some imperative methods to a parent
component with the useImperativeHandle Hook.
If you’re not familiar with this syntax, check out the explanation in the State Hook
documentation.
Performance Optimizations
Yes. See conditionally firing an effect. Note that forgetting to handle updates often introduces
bugs, which is why this isn’t the default behavior.
You can wrap a function component with React.memo to shallowly compare its props:
It’s not a Hook because it doesn’t compose like Hooks do. React.memo is equivalent to
PureComponent , but it only compares props. (You can also add a second argument to specify
a custom comparison function that takes the old and new props. If it returns true, the update is
skipped.)
React.memo doesn’t compare state because there is no single state object to compare. But
you can make children pure too, or even optimize individual children with useMemo .
The useMemo Hook lets you cache calculations between multiple renders by “remembering”
the previous computation:
This code calls computeExpensiveValue(a, b) . But if the inputs [a, b] haven’t changed since the
last value, useMemo skips calling it a second time and simply reuses the last value it returned.
Remember that the function passed to useMemo runs during rendering. Don’t do anything
there that you wouldn’t normally do while rendering. For example, side effects belong in
useEffect , not useMemo .
You may rely on useMemo as a performance optimization, not as a semantic guarantee.
In the future, React may choose to “forget” some previously memoized values and recalculate
them on next render, e.g. to free memory for offscreen components. Write your code so that it
still works without useMemo — and then add it to optimize performance. (For rare cases when
a value must never be recomputed, you can lazily initialize a ref.)
function Parent({ a, b }) {
// Only re-rendered if `a` changes:
const child1 = useMemo(() => <Child1 a={a} />, [a]);
// Only re-rendered if `b` changes:
const child2 = useMemo(() => <Child2 b={b} />, [b]);
return (
<>
{child1}
{child2}
</>
)
}
Note that this approach won’t work in a loop because Hook callscan’t be placed inside loops.
But you can extract a separate component for the list item, and call useMemo there.
useMemo lets you memoize an expensive calculation if the inputs are the same. However, it
only serves as a hint, and doesn’t guarantee the computation won’t re-run. But sometimes you
need to be sure an object is only created once.
The first common use case is when creating the initial state is expensive:
function Table(props) {
// ⚠️ createRows() is called on every render
const [rows, setRows] = useState(createRows(props.count));
// ...
}
To avoid re-creating the ignored initial state, we can pass afunction to useState :
function Table(props) {
// createRows() is only called once
const [rows, setRows] = useState(() => createRows(props.count));
// ...
}
React will only call this function during the first render. See the useState API reference.
You might also occasionally want to avoid re-creating theuseRef() initial value. For
example, maybe you want to ensure some imperative class instance only gets created once:
function Image(props) {
// ⚠️ IntersectionObserver is created on every render
const ref = useRef(new IntersectionObserver(onIntersect));
// ...
}
useRef does not accept a special function overload like useState . Instead, you can write your
own function that creates and sets it lazily:
function Image(props) {
const ref = useRef(null);
This avoids creating an expensive object until it’s truly needed for the first time. If you use Flow
or TypeScript, you can also give getObserver() a non-nullable type for convenience.
No. In modern browsers, the raw performance of closures compared to classes doesn’t differ
significantly except in extreme scenarios.
In addition, consider that the design of Hooks is more efficient in a couple ways:
Hooks avoid a lot of the overhead that classes require, like the cost of creating class instances
and binding event handlers in the constructor.
Idiomatic code using Hooks doesn’t need the deep component tree nestingthat is
prevalent in codebases that use higher-order components, render props, and context. With
smaller component trees, React has less work to do.
Traditionally, performance concerns around inline functions in React have been related to how
passing new callbacks on each render breaks shouldComponentUpdate optimizations in child
components. Hooks approach this problem from three sides.
The useCallback Hook lets you keep the same callback reference between re-renders so that
shouldComponentUpdate continues to work:
The useMemo Hook makes it easier to control when individual children update, reducing the
need for pure components.
Finally, the useReducer Hook reduces the need to pass callbacks deeply, as explained below.
We’ve found that most people don’t enjoy manually passing callbacks through every level of a
component tree. Even though it is more explicit, it can feel like a lot of “plumbing”.
function TodosApp() {
// Note: `dispatch` won't change between re-renders
const [todos, dispatch] = useReducer(todosReducer);
return (
<TodosDispatch.Provider value={dispatch}>
<DeepTree todos={todos} />
</TodosDispatch.Provider>
);
}
Any child in the tree inside TodosApp can use the dispatch function to pass actions up to
TodosApp :
function DeepChild(props) {
// If we want to perform an action, we can get dispatch from context.
const dispatch = useContext(TodosDispatch);
function handleClick() {
dispatch({ type: 'add', text: 'hello' });
}
return (
<button onClick={handleClick}>Add todo</button>
);
}
This is both more convenient from the maintenance perspective (no need to keep forwarding
callbacks), and avoids the callback problem altogether. Passing dispatch down like this is the
recommended pattern for deep updates.
Note that you can still choose whether to pass the applicationstate down as props (more
explicit) or as context (more convenient for very deep updates). If you use context to pass
down the state too, use two different context types — the dispatch context never changes, so
components that read it don’t need to rerender unless they also need the application state.
Note
We recommend to pass dispatch down in context rather than individual callbacks in props. The
approach below is only mentioned here for completeness and as an escape hatch.
Also note that this pattern might cause problems in theconcurrent mode. We plan to provide
more ergonomic alternatives in the future, but the safest solution right now is to always
invalidate the callback if some value it depends on changes.
In some rare cases you might need to memoize a callback with useCallback but the
memoization doesn’t work very well because the inner function has to be re-created too often.
If the function you’re memoizing is an event handler and isn’t used during rendering, you can
use ref as an instance variable, and save the last committed value into it manually:
function Form() {
const [text, updateText] = useState('');
const textRef = useRef();
useLayoutEffect(() => {
textRef.current = text; // Write it to the ref
});
return (
<>
<input value={text} onChange={e => updateText(e.target.value)} />
<ExpensiveTree onSubmit={handleSubmit} />
</>
);
}
This is a rather convoluted pattern but it shows that you can do this escape hatch optimization
if you need it. It’s more bearable if you extract it to a custom Hook:
function Form() {
const [text, updateText] = useState('');
// Will be memoized even if `text` changes:
const handleSubmit = useEventCallback(() => {
alert(text);
}, [text]);
return (
<>
<input value={text} onChange={e => updateText(e.target.value)} />
<ExpensiveTree onSubmit={handleSubmit} />
</>
);
}
useLayoutEffect(() => {
ref.current = fn;
}, [fn, ...dependencies]);
In either case, we don’t recommend this pattern and only show it here for completeness.
Instead, it is preferable to avoid passing callbacks deep down.
React keeps track of the currently rendering component. Thanks to theRules of Hooks, we
know that Hooks are only called from React components (or custom Hooks — which are also
only called from React components).
There is an internal list of “memory cells” associated with each component. They’re just
JavaScript objects where we can put some data. When you call a Hook like useState() , it reads
the current cell (or initializes it during the first render), and then moves the pointer to the next
one. This is how multiple useState() calls each get independent local state.
React community’s experiments with render prop APIs, includingRyan Florence’s Reactions Component.
Dominic Gannaway’s adopt keyword proposal as a sugar syntax for render props.
Subscriptions in Rx.
Sebastian Markbåge came up with the original design for Hooks, later refined byAndrew Clark,
Sophie Alpert, Dominic Gannaway, and other members of the React team.
Previous article
Hooks API Reference
D O C S C H A N N E L S C O M M U
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooks (New)ContributingFAQ GitHub Stack Overflow Discussion Forum Reactiflux Chat DEV Community Facebook Community
Twitter Resources