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 
    }
}

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 setBackgroundColorsetFontFamily, 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.

Comments

Popular posts from this blog

Flutter for Single-Page Scrollable Websites with Navigator 2.0

A Data Science Portfolio is More Valuable than a Resume

Better File Storage in Oracle Cloud