DEV Community

Cover image for React Hooks: useState
Hajar | هاجر
Hajar | هاجر

Posted on • Edited on

React Hooks: useState

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 
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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>
    )}
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

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}} 
Enter fullscreen mode Exit fullscreen mode

Let's take a closer look at this line of code:

let [backgroundColor, setBackgroundColor] = useState("lightblue");
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

Back to our first question. What do you think that line of code does?

let [backgroundColor, setBackgroundColor] = useState("lightblue");
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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)