Introduction
In the
previous article, we learned about useState hook along with its various examples and usage with the functional components. In this article, we will learn about useEffect() hooks and how to use them in React.
useEffect() in React
The React useEffect hook allows adding side-effects in a functional component.
Previously, in-class component, we saw that to perform side effects, we need to use component life cycle methods like componentDidMount(), componentDidUpdate() and componentWillMount(). In class component, when any update is needed via the lifecycle, we need to call it twice, but this is not the case when using Hooks.
For example, to update the title of a document in the browser, we have the below code using class component.
- import React, { Component } from 'react'
- class UseEffectDemo extends Component {
- constructor(props) {
- super(props)
- this.state = {
- title: 'React'
- }
- this.updateTitle = this.updateTitle.bind(this)
- }
- updateTitle(e) {
- this.setState({
- title: e.target.value
- })
- e.preventDefault();
- }
- componentDidMount() {
- document.title = `New ${this.state.title}`
- }
- componentDidUpdate() {
- document.title = `New ${this.state.title}`
- }
- render() {
- return (
- <div>
- <input type="text" value={this.state.title} onChange={this.updateTitle}></input>
- </div>
- )
- }
- }
- export default UseEffectDemo
This will display an output as below.
As we type further, the title is getting updated automatically.
Now, we will look at the same demo using useEffect() Hook.
Let us create a function in UseEffectHook.js.
- import React, { useState, useEffect } from 'react'
- function UseEffectFunction() {
- const initialTitle = 'React'
- const [title, setTitle] = useState(initialTitle);
- useEffect(() => {
- document.title = `New ${title}`
- })
- return (
- <div>
- <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
- </div>
- )
- }
- export default UseEffectFunction
This will display the same output as a class component.
Initially, it will display the value as React.
Later, as we type in the textbox, the same value will get updated in the title. So, the useEffect() hook will run on first, as well as, every render to update the values as per your requirement.
One thing to remember while using useEffect() hook is that it should be defined within the component. This will help to access all properties and the state of component without additional code.
Now, we will run useEffect() on every render. It should run conditionally.
useEffect() call conditionally
Now, let’s check how to not re-render unnecessarily in both, class as well as a functional component.
- import React, { Component } from 'react'
- class UseEffectDemo extends Component {
- constructor(props) {
- super(props)
- this.state = {
- title: 'React'
- }
- this.updateTitle = this.updateTitle.bind(this)
- }
- updateTitle(e) {
- this.setState({
- title: e.target.value,
- count: 0
- })
- e.preventDefault();
- }
- componentDidMount() {
- document.title = `New ${this.state.title}`
- }
- componentDidUpdate(prevProps, prevState) {
- console.log("Render componentDidUpdate")
- document.title = `New ${this.state.title}`
- }
- render() {
- return (
- <div>
- <label>Button Clicked {this.state.count}</label>
- <input type="text" value={this.state.title} onChange={this.updateTitle}></input>
- <button onClick={() => this.setState({ count: this.state.count + 1 })}>Click Me</button>
- </div>
- )
- }
- }
- export default UseEffectDemo
In the output, when we write in textbox, the render method is called. Now, on click of the button, it is again rendering, which is not required.
So, in the console, we can see that render is called multiple times.
Now, we will restrict the assignment of new value every time.
- import React, { Component } from 'react'
- class UseEffectDemo extends Component {
- constructor(props) {
- super(props)
- this.state = {
- title: 'React'
- }
- this.updateTitle = this.updateTitle.bind(this)
- }
- updateTitle(e) {
- this.setState({
- title: e.target.value,
- count: 0
- })
- e.preventDefault();
- }
- componentDidMount() {
- document.title = `New ${this.state.title}`
- }
- componentDidUpdate(prevProps, prevState) {
- if (prevState.title !== this.state.title) {
- console.log("Render componentDidUpdate")
- document.title = `New ${this.state.title}`
- }
- }
- render() {
- return (
- <div>
- <label>Button Clicked {this.state.count}</label>
- <input type="text" value={this.state.title} onChange={this.updateTitle}></input>
- <button onClick={() => this.setState({ count: this.state.count + 1 })}>Click Me</button>
- </div>
- )
- }
- }
- export default UseEffectDemo
The output will be as below.
Now, we will look at the same code for Functional component.
- import React, { useState, useEffect } from 'react'
- function UseEffectFunction() {
- const initialTitle = 'React'
- const [title, setTitle] = useState(initialTitle);
- const [count, setCount] = useState(0)
- useEffect(() => {
- console.log("useEffect rendered")
- document.title = `New ${title}`
- })
- return (
- <div>
- <label>Button clicked {count}</label>
- <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
- <button onClick={() => setCount(count + 1)}>Click Me</button>
- </div>
- )
- }
- export default UseEffectFunction
The output will be as below.
So, after clicking on the button, useEffect() is called every time.
To prevent it from happening, we have the functionality within useEffect() function.
We can pass a variable within it, as shown in the code below.
- import React, { useState, useEffect } from 'react'
- function UseEffectFunction() {
- const initialTitle = 'React'
- const [title, setTitle] = useState(initialTitle);
- const [count, setCount] = useState(0)
- useEffect(() => {
- console.log("useEffect rendered")
- document.title = `New ${title}`
- }, [title])
- return (
- <div>
- <label>Button clicked {count}</label>
- <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
- <button onClick={() => setCount(count + 1)}>Click Me</button>
- </div>
- )
- }
- export default UseEffectFunction
The output will be displayed as below.
Summary
In this article, we have learned the concept of useEffect(), how it is used or defined, and how it can be implemented to call conditionally.
You can download the source code attached to this article. In the next article, we are going to learn about how to use the useEffect() hook to call only once is some scenarios and use it with cleanup which will prevent a memory leak.