Before I knew that React Hooks had even existed, I used to read advise like, "Always use functional components instead of class components in React." Which means always declare your components as functions instead of as classes. Or in code:
//use
const Component = ()=>{
// return code here
}
//instead of
class Component extends React.Componet{
render(){
// return code here
}
}
I tried to follow that advice for a little while. However, the moment I wanted to use state in my component, that advice seemed useless. I had to refactor my code and use a class component instead of a functional component. I thought that was the only way to use state or any of the lifecycle methods in React. Little did I know.
I then learned about Hooks, and that advice started to make a lot more sense.
The first few things that I have learned about React Hooks are:
1- Hooks allow us to use state and other features without having to write a class.
2- We only call them from functional components.
3- We only call them at the top level, not inside loops, conditions, or nested functions.
let us write a simple class component that changes the background color of a div element and then see how we can refactor it to use the useState hook.
class App extends React.Component {
constructor(props){
super(props);
this.state= {
backgroundColor: "lightblue",
}
}
changeBackgroundColor = ()=>{
this.setState({ backgroundColor: getRandomColor() })
}
render(){
return(
<main>
<div
style={{backgroundColor:this.state.backgroundColor }}
className="circle"
/>
<button onClick={this.changeBackgroundColor}>Change Color</button>
</main>
)}
}
const getRandomColor = ()=>{
return "#" + Math.random().toString(16).slice(2,8);
}
That looks like a lot of code for something that does nothing but randomly change a background color, right?
Let's see the changes that will happen when using the useState hook.
import React, { useState } from 'react';
const App =()=> {
// 1
let [backgroundColor, setBackgroundColor] = useState("lightblue");
const changeBackgroundColor = ()=>{
// 2
setBackgroundColor(getRandomColor())
}
return(
<main>
{/* 3 */}
<div
style={{backgroundColor:backgroundColor}}
className="circle"
/>
{/* 4 */}
<button onClick={changeBackgroundColor}>Change Color</button>
</main>
)}
First, we replaced four lines of writing a constructor and using this.state with just one line.
// Old code
constructor(props){
super(props);
this.state= {
backgroundColor: "lightblue",
}
}
// New code
let [backgroundColor, setBackgroundColor] = useState("lightblue");
Second, we don't have to use this.setState to update the state variables anymore.
// Old code
this.setState({ backgroundColor: getRandomColor() })
//New code
setBackgroundColor(getRandomColor())
And finally, we no longer have to get confused by using lots of this and this.state.<variable_name>
// Old code
onClick={this.changeBackgroundColor}
style={{backgroundColor:this.state.backgroundColor}}
// New code
onClick={changeBackgroundColor}
style={{backgroundColor:backgroundColor}}
Let's take a closer look at this line of code:
let [backgroundColor, setBackgroundColor] = useState("lightblue");
What do you think this line does? And what if we wanted to change, let’s say, the font-family instead of the background-color, what do you think would change?
Answering the second question first, if we wanted to change the font-family we would write:
Let [fontFamily, setFontFamily] = useState("Arial"); // setting Arial as the initial value of the font-family.
//Or
Let [font, setFont] = useState("Arial"); // you can name your variables whatever you want.
Back to our first question. What do you think that line of code does?
let [backgroundColor, setBackgroundColor] = useState("lightblue");
That line does three things, actually.
1- It declares a variable named backgroundColor.
2- It gives that variable an initial value of lightblue.
3- It declares a function named setBackgroundColor that is now responsible for updating the backgroundColor’s value whenever we need.
So now, why does this happen?
When we call the useState hook and pass it a value, it returns an array of two items. The first item is a state variable and set to the value that is passed to the useState hook. The second item is a function that is responsible for updating the first variable.
When we write,
let [backgroundColor, setBackgroundColor] = useState("lightblue");
we use the array destruction to assign the backgroundColor variable and the setBackgroundColor function to the two items of the array that's returned from calling the useState hook.
The last thing I want to mention here is that we can use the useState hook multiple times in our components.
If we wanted to change the background-color, the font-family and the border of a component we would write something like this:
const [backgroundColor, setBackgroundColor] = useState("yellow");
const [fontFamily, setFontFamily] = useState("Arial");
const [borer, setBorder] = useState("1px solid teal");
Then use all the setBackgroundColor, setFontFamily, and setBorder functions to update the background-color, the font-family, and the border, respectively.
I think that is all I know about the useState hook so far.
Thank you for reading.
Top comments (0)