React.useEffect reference
This post is all over the place – just like my understanding of useEffect 🙃
useEffect lets you synchronize side-effects with component state
To make your UI’s behavior predictable and to avoid subtle bugs, the React docs recommend you write your components as pure functions so that given the same props, they always return the same JSX.
But sometimes you need your components to respond to user actions or to interact with external systems. For example:
- Display a modal when the user clicks a button.
- Focus an input element when a component first mounts
- Fetch data from a server when a component first mounts.
- Setup subscriptions to external services (e.g., Firebase’s Cloud Firestore or a GraphQL server)
You usually place these side effects inside event handlers. Event handlers don’t run during the component’s rendering phase, so they don’t need to be pure.
But sometimes you can’t find a suitable event handler for a side-effect. For example, you can display a modal on the click of a button like so:
<Button onClick={() => { showModal('blah') }>Show modal</Button>
But it’s not obvious what event handler you could use if you wanted to fetch external data when a component first mounts. When you’ve exhausted all other options, you can use useEffect
as a last resort.
You can use useEffect
to tell React to execute a side-effect whenever a piece of component state changes – this can be a state created with useState
, a prop, or a value computed from state or prop.
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Execute effect every time `count` changes
}
When does useEffect
run in the component lifecycle?
After the first render
When the component is initially mounted on the DOM and has finished rendering. You will have access to the initial state and props inside your effect. If you don’t want to execute the effect on the first render, see this post.
After every subsequent render
Every time the component has finished re-rendering, your effect will be executed. If you’ve specified any dependencies, it will run only if one of the dependencies changed since the last render.
useEffect
doesn’t block the browser painting process
Unlike componentDidMount
or componentDidUpdate
, effects scheduled with useEffect
are deferred and executed after the browser has finished its layout and painting process. If you need to perform an effect before the next browser paint, you can use the useLayoutEffect
instead.
Although deferred until after the browser has painted, useEffect
is guaranteed to fire before the component is re-rendered. React will always finish a previous effect before starting a new re-render (need a working example of this).
useEffect vs class component life cycle methods
useEffect
is a replacement for the following lifecycle methods in a class component:
In class components, you place side-effects in the componentDidMount
and componentDidUpdate
methods. You clean up the side-effects in componentWillUnmount
.
So, the following class component:
import React from 'react'
class Example extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`
}
componentWillUnmount() {
// Do some clean up
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
)
}
}
can be written as a functional component that uses useEffect
:
import React, { useState, useEffect } from 'react'
function Example() {
const [count, setCount] = useState(0)
useEffect(() => {
document.title = `You clicked ${count} times`
return () => {
// Do some clean up
}
})
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
)
}
How to use
- React patterns: Run effect only on mount
- React patterns: Run effect after every render
- React patterns: Run effect only if dependencies change
- React patterns: Clean up effect when component unmounts
Other notes
The effect function will be different on every render
Every time a component is rendered (either initially or subsequently), the effect function will be a different function in the sense that it will be a new entity in the JavaScript engine’s memory heap.
Random
Sources
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment