Introduction of useState and useEffect
source link: https://dev.to/yohanesss/introduction-of-usestate-and-useeffect-20do
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Introduction of useState and useEffect
You are a developer with previous experience using React, and you are comfortable using React class components. You're so comfortable with class components that switching to functional components sounds daunting. How will you manage the situation? How can you access the React component lifecycle?
If this sounds like you, then this guide will help you start transitioning your class components into functional components. React hooks provide the ability to use state and lifecycle functions inside functional components.
We'll cover the two built-in React hooks: useState
and useEffect
.
useState
The main difference between class and functional components is the fact that class components have state whereas functional components have no state. The useState hook lets us add a local state to a functional component. This hook holds the state between re-renders.
Let's start by comparing the class component and functional component.
import React from 'react';
class Increment extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
this.setCounter = this.setCounter.bind(this);
}
setCounter() {
this.setState({
counter: this.state.counter + 1
});
}
render() {
return(
<div>
<h1>Counter: {this.state.counter}</h1>
<button onClick={this.setCounter}>Increment</button>
</div>
)
}
}
Enter fullscreen mode
Exit fullscreen mode
In code above, we have a stateful component. Since you are already familiar with class components, let's keep this explanation brief.
A constructor is created at the start of the component and sets the initial state.
counter
is the only value in this example and is initially set to0
.To update the state,
this.setState
is called insetCounter
function.The
onClick
event in the button tag callssetCounter
, allowing the state to be updated.
How we can we achieve the same thing in stateless component?
import React, { useState } from 'react';
const Increment = () => {
const [counter, setCounter] = useState(0);
function incrementByOne() {
setCounter(counter + 1);
}
return (
<div>
<h1>Counter: {counter}</h1>
<button onClick={incrementByOne}>Increment</button>
</div>
);
}
Enter fullscreen mode
Exit fullscreen mode
Now let's describe what happens in this stateless component:
Importing the
useState
hooks.Declaring a state variable for the component. We are using array destructuring to get the getter and setter methods, and the parameter passed in the
useState
hooks is the initial value for our state. In this casecounter
is the getter andsetCounter
is the setter and the initial value is0
.To update the state,
setCounter
is called inincrementByOne
function.The onClick event in the button tag calls
setCounter
, allowing the state to be updated.
With this, we finished replicating the state management from class component into functional component. Hooray!
useEffect
The useEffect
hook allows us to implement lifecycle methods to tell the component to perform an side effect after rendering. The different types of effects are not limited like changing document title, adding animation or music, data retrieval, and subscriptions.
As mentioned earlier, the useEffect
hook allows us to use React's lifecycle methods in stateless components. We'll look at mirroring the effects of componentDidMount
and componentDidUpdate
.
import React from 'react';
class FavoriteVehicle extends React.Component {
constructor(props) {
super(props);
this.state = {
vehicle: 'Walk ๐'
};
componentDidMount() {
console.log(`Component mounted | ${this.state.vehicle}`);
}
componentDidUpdate() {
console.log(`Component updated | ${this.state.vehicle}`);
}
changeToCar() {
this.setState({ vehicle: 'Car ๐' })
}
changeToRocket() {
this.setState({ vehicle: 'Rocket ๐' })
}
render() {
return(
<div>
<h1>My Fav Vehicle: {this.state.vehicle}</h1>
<button onClick={changeToCar}>Change to Car ๐</button>
<button onClick={changeToRocket}>Change to Rocket ๐</button>
</div>
);
}
}
}
Enter fullscreen mode
Exit fullscreen mode
componentDidMount
will be called as soon as the component is mounted. In our example, when FavoriteVehicle
is rendered, the string "Component mounted | Walk ๐"
will appear in console.
When you click the "Change to Car ๐"
button, componentDidUpdate
is called (because the state has changed), the console will print "Component updated | Car ๐"
. If you click the "Change to Rocket ๐"
button componentDidUpdate
will be called again. componentDidUpdate
will be executed every time the component is re-rendered.
How we can achieve the same thing in functional component? Let's see the code below.
import React, { useState, useEffect } from 'react';
const FavoriteVehicle = () => {
const [vehicle, setVehicle] = useState('Walk ๐');
useEffect(() => {
console.log(`Component mounted | ${vehicle}`);
}, []);
useEffect(() => {
console.log(`Component updated | ${vehicle}`);
}, [vehicle])
return(
<div>
<h1>My Fav Vehicle: {vehicle}</h1>
<button onClick={() => setVehicle('Car ๐')}>Change to Car ๐</button>
<button onClick={() => setVehicle('Rocket ๐')}>Change to Rocket ๐</button>
</div>
);
}
Enter fullscreen mode
Exit fullscreen mode
Let's describe what happened here:
Importing
useState
anduseEffect
hooksWe called
useEffect
in our functional component.useEffect
accept two parameters, the first parameter is the effect callback, and the second parameter is dependency array. Notice that we called it twice in this example. When we called it the first time, we pass empty array, and on the second time we passvehicle
as our dependency. There is a subtle difference in both of theseuseEffect
invocations.If we pass empty array to our
useEffect
invocation it will only run once, therefore it will behave same ascomponentDidMount
. Otherwise when we passvehicle
on dependency list, our component will re-render every time if the value ofvehicle
is changed, it will behave same ascomponentDidUpdate
.When the component is rendered we will see both
"Component mounted | Walk ๐"
and"Component updated | Walk ๐"
is logged in console. And when we tried to click"Change to Car ๐"
, we will see"Component updated | Car ๐"
is logged in console. This happen because we passvehicle
in our dependency array inuseEffect
hook. Note that"Component mounted | Walk ๐"
is only logged once this happen because we didn't pass anything in our dependency array.
Another thing to note is, if we only pass one parameter (the effect callback) into useEffect
, the effect will be always executed after every render. There will be a nasty bug in your code if you're trying to set the state in useEffect
without putting the state in the dependency array. Let's say maybe you're fetching userData from API and tried to save the returned data into your state. You will have an infinite re-render of your component! ๐งจ ps: When I first learn about useEffect this happen to me. I tell you so hopefully you are not suffer the same thing that I experienced. LOL'
The last thing that I want to mentioned is you also can mimic componentWillUnmount
behavior in useEffect
by having a return function in your effect callback. useEffect
will invoke this function when unmounting the component. This is useful when you want to unsubscribe to some listener API or to cleaning up async effect in your component.
That's it for the introduction of useState
and useEffect
. I hope this article will help you in your journey to understanding react hooks ๐ป
Recommend
-
33
Yeah, this article is based on Advance hooks, so I assume that you are aware of hooks and familiar with the usage of basic hooks like useState and useEffect. So if you donโt know about hooks you can look it up in the
-
20
...
-
6
I love mental models. Theyโre crucial to understanding complex systems, allowing us to intuitively grasp and solve complex problems. This is the second of a three-part series of articles around React mental mode...
-
9
React Hooks Tutorial | useState() and useEffect() This tutorial help to understand How to use React Hooks useState() and useEffect(). Weโll learn to React hooks step by step into this react tutorial. Also, have...
-
4
A more granular useEffectEver needed to run an effect when certain dependencies changed, but not others?useEffect is one of the most essentials React hooks. Whether you n...
-
14
Under the Hood of React useEffect DependenciesA deep dive into the dependencies array in React.useEffect(). What causes stale values from previous renders in ReactThere is so much confusion around the d...
-
3
React first introduced Hooks in version 16.8, and they have changed th...
-
3
React useEffect and HTTP callsReact useEffect and HTTP calls08/06/2022The motivation behind the introduction of useEffect Hook is to eliminate the...
-
3
In React, useState and useReducer are commonly used for managing state. While useImmer is a popular alternative to useState, in this article, we will explore h...
-
10
Choosing between useReducer and useState in React Mar 30, 2023 โข
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK