Prerequisite:
In this blog, I assume that you have some basic understanding of Reactjs concepts like state and lifecycle method!
Aim:
To help you make a transition from class-based components to functional-based components using react hooks!
Now, without any further ado, let's get started...
Me:
I hope you are Excited! 😋
You:
What are Hooks?
Hooks are functions that let you “hook into” React state and lifecycle features from function components.
Since earlier we were able to use the concept of state
and lifecycle
in class-based components
only, but now with help of hooks
, we'll be able to use it in functional components
also!
So, now we don't need to write class-based components anymore!
State - useState Hook
In Class-Based Component
example,
class Counter extends React.Component{
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
Now, In the Functional-Based component
example
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Explanation: So, useState
is a hook that lets you add React state into functional Components!
PART-1 Creating state
//syntax
const [state,setState] = useState(initialvalue)
//Example
const [count,setCount] = useState(0)
useState
takes an initial value here we have given it as0
and returns us an array which on destructuring gives variablecount
and functionsetCount
.count
variable whose value is 0 (initial value taken by useState is assigned to variable)setCount
function is used to update thecount
variable whenever we need!
Note 1:
Here, count == this.state.count
and setCount(count + 1) == this.setState({ count: count + 1 })
Note 2: You can name count
and setCount
anything you wish to!
PART-2 Reading State
// In Class Component it is read as
<p>You clicked {this.state.count} times</p>
// In Functional Component
<p>You clicked {count} times</p>
PART-3 Updating State
// In Class based component
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
// In Functional Component
<button onClick={() => setCount(count + 1)}>
Click me
</button>
You:
Lifecycle - useEffect Hook
useEffect hook helps us to perform side effects in functional components!
- useEffect takes an
Anonymous function
and execute it after performing the DOM updates!
Example: This is useEffect without cleanup function
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
// by default runs after every render, replacing effect everytime!
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Explanation: After 1st render, useEffect will run and update our document title to You clicked 0 times
since the initial value of the count
state is 0. And after every click count
state updates its value, so, useEffect
also execute its effect and updates the document title with the current value of count
!
Note1: You can make all API calls i.e Data fetching, setting a subscription and manually changing DOM in react components can be performed in useEffect
Note2: This is similar to componentDidMount
and componentDidUpdate
This is an equivalent example based on a class-based component!
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`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
Does useEffect run after every render?
Yes! By default, it runs both after the first render and after every update. Don't worry 😆! We can customize this.
Example: useEffect with the cleanup function
// In Functional way
useEffect(() => {
// some async call
fetchUsersData()
// equal to `componentWillmount` i.e executed when component unmounts
return function cleanUp() {
console.log("Users component is unmounted")
}
})
// In class component
componentDidMount() {
fetchUsersData()
}
componentWillUnmount(){
console.log("Users component is unmounted")
}
Explanation: 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.
Hence componentDidMount
, componentDidUpdate
and componentWillUnmount
all combined in one useEffect
hook!
You
:
Customize useEffect hook
- First Customization!
Let's suppose you are making some backend calls to a API for fetching all users data. Now we want to make that call only one time after component renders!
And since useEffect
runs after every render, so we need to add dependency array
as 2nd argument i.e
useEffect(() => {
fetchUsersData()
}, [])
// this [] empty array tells Effect to run only once after 1st render
If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar
componentDidMount
andcomponentWillUnmount
mental model
- Second Customization!
Suppose you only want to run useEffect
when the count
state variable changes and not after every render happens or once.
For that, we need to give the count
variable in the dependencies
array i.e
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
// Only re-run the effect if count changes
Note: If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect.
Rules of Hooks!
- Only call Hooks
at the top level
. Don’t call Hooks inside loops, conditions, or nested functions. - Only call Hooks
from React function components
. Don’t call Hooks from regular JavaScript functions.
That's all! We're done with the basics of hooks!
Reference: React Docs
Summary!
Thank you to everyone for making till the end!
We'll meet soon in next blog! 💙