Complete guide to understanding the React UseState hook
Tags: react, javascript, webdev, beginners
Published: 2022-05-05 18:10:22

Hello World, in this article, we take a dive on how to manage states in our React application using the `useState` hook.

By the time you finish reading the article, you should be able to 
- Understand `state`
- How to implement the `useState` hook
- How to update `state` in your application , and some rules in using the `useState` hook

Let's get started. 

## Understanding State in React

> State is data or value that is subject to change in our application. It describes the condition of our app at any point in time.

Because we build dynamic web apps in React, we will expect the data (information) in our app to change in response to a user's action. 
These actions could be a user: 
- Clicking on a button
- Entering a value in a form field 
- Submitting a form.
- Clicking on the next button on an image carousel.

Anytime `state` (data or information) changes in React, the component will re-render and display the updated information on the screen as a result of the above interactions. 

State can be of any data type, it can be an `object`, `array`, a `string`, `boolean` etc. 

The code below demonstrate how to use state in a component.

### Using State in a component 

```
import React from "react"
import "./styles.css";

export default function App() {
  // defining a regular variable
  const userMsg = "Start learning React Hooks";

  return (
    <div className="App">
      <h1>Hello User</h1>
      <h2>{userMsg}</h2>
      <button>Get Started </button>

    </div>
  );
}

```
In the code above:

- We defined a  "regular" variable `userMsg` which we will call `state` variable (for now)
- We then assign some value to the `userMsg` 
- In our JSX template, we output the information stored in  the `userMsg` like this `{userMsg}`
- Doing this, we preserve the (state) value between function calls. Anytime the app reloads, we will still see the value stored in the `userMsg` on the screen. 

### Displaying the state in our UI

With the code above, when we launch our app we should see the below on our screen:

```
Hello User
Start learning React Hooks
```

### Changing State In React. 

We usually want the state (data or information) on the UI to change when an event occurs on the app. For instance, a user clicking on a button.

Let's take a look at how to change the state in our app. 

- We want the state (*value or data* ) to change from `Start learning React Hooks` to `Lesson one: React useState Hook` when a user clicks on the `Get Started` button.

- We declared a function `handleUserMsg`, which will responsible for updating the value when we click on the `Get Started` button.
- The `handleUserMsg` function will be invoked, and in the body of the function, we will assign the **new value.**  to the `userMsg` variable.

See the code below 

```
import React from "react";
import "./styles.css";

export default function App() {
  // defining a  regular variable
  const userMsg = "Start learning React Hooks";

  const handleUserMsg = () => {
// assigning a new value to the variable
   userMsg = "Lesson one: React useState Hook"
  };
  return (
    <div className="App">
      <h1>Hello User</h1>
      {/* using the state  */}
      <h2>{userMsg}</h2>
      <button onClick={handleUserMsg}>Get Started</button>
    </div>
  );1
}
```

What is happening in the code above:
- On the click of the "Get Started" button, the `handleUserMsg` function is invoked, and `Lesson one: React useState Hook` is now assigned to the `userMsg` variable. 
- With that, we have updated the value (*this is how we learnt to assign a new value to a variable in JavaScript*)

### Re-rendering component when state changes.
When we assign a new value to our `state` variable in React, our app will need to reload (re-render) to display the updated data (information).

In the code above:
- We assigned `Lesson one: React useState Hook` to the `userMsg` variable when the `handleUserMsg` function is executed.
- When the `handleUserMsg` function is invoked, the state (data or value has changed), and we **will expect the browser to re-render to output the code below on the user interface:**

```
Hello User
Lesson one: React useState Hook
```
Note: **But it does not**, let's find out why in the next section.

### Exploring "reactivity" in regular variables

Even though we expect the browser to output  the latest data, assigned to the `userMsg` variable, clicking the `Get Started` button **does not update** the  state (data) from `Start learning React Hooks ` to `Lesson one: React useState Hook `.

We can actually prove the new State `Lesson one: React useState Hook ` was assigned to `userMsg`
- `console.log(userMsg)` in the `handleUserMsg` function, as illustrated in the code above

The `handleUserMsg()` event handler is updating the regular variable `userMsg`. However, the change is not visible due to the below:

- The `userMsg` variable declared above, is considered a "regular" variable, and "regular" variables do not carry on between renders.
- When the component is rendered again, it  **does not consider any new value assigned to the regular variables.** 
- Hence, any update to "regular" variables won't trigger renders (React doesn't realize it needs to render the component again with the new value).

### States Should be Reactive
The value stored in the `userMsg` variable has changed, but the **change is not reflecting on the user interface**. 

**This is because the value stored in the `userMsg` variable is only a regular variable and  not reactive. **

What this means is:

- React does not track the regular variable for changes
- When the value changes, it will not trigger React to re-render the component to reflect the update.
- Hence, we continue to see the **initial value** `Start learning React Hooks` on the user interface. 
 

### Updating a component with new data.
To update a component with the  new data, we need to make the value 'reactive'.  

The below need to happen:

- Retain the data between renders
- Cause React to render the component with new data (re-rendering)

To **update the component with new data**, we need to rely on the `useState` hook. It will provide these two things:

- First is a state variable to retain the data between renders
- Secondly, a setter function to upate the variable and  trigger React to render the component again.

Using the `useState` hook, React can track the changes in the value, by **comparing the new value to the initial value**. 

Let's now make our state reactive using the `useState()` hook.

### What is the useState hook ?

> The useState() hook enables you to add `state variables` in functional components. It allows developers to track changes, update and manipulate state inside functional components without needing to convert it to a class component.

#### Syntax for the useState hook 
The syntax for the `useState` hook is as below 

```
const [state, setState] = useState(initialState)
``` 

#### How to use the `useState` hook

In order to use the `useState()` hook,  we need to import it from `react` library like the below 

```
import React,{useState} from "react";
```

- Now that we have imported the `useState()` hook, we can use it in our functional component and pass it a **reactive value**. 
- The  reactive value is the **initial value or initial state** you want to display on the user interface.

In code below, we call the `useState` hook and pass it our initial state

```
... = useState("Start learning React Hooks");
```
Below is the complete code, let's break it down further:

```
import React, { useState } from "react";
import "./styles.css";

export default function App() {

//calling the useState hook and passing the initial value
  const [userMsg, setUserMsg] = useState("Start learning React Hooks");

//function to change the state
const handleUserMsg = () => {
//update the state inside this function's body 
};
  return (
    <div className="App">
      <h1>Hello User</h1>
      <h2>{userMsg}</h2>
      <button onClick={handleUserMsg}>Get Started</button>
    </div>
  );
}

```


####  Under the hood of useState hook
When the `useState()` hook is called like this : `useState("Start learning React Hooks")`, it returns an **array with two values**:

- First, is the **initial state** value 
- Next, a function called the `setter` responsible for updating the current state

We then use `array destructuring` in JavaScript to store the values returned by calling the `useState()` function into distinct variables: `userMsg` and `setUserMsg`.

```
const [userMsg, setUserMsg] = useState("Start learning React Hooks");

```
 In the code above: 
- The initial state is stored in the  `userMsg` variable
- The setter function which is responsible for updating the current state will be stored in the `setUserMsg` variable. 
- The variable names is entirely up to you. By convention, we name state variables like `[someState, setSomeState]`.

#### Reading the state variable 

The initial value stored in the `userMsg` variable can be read . We use it in our JSX template like `{userMsg}`

```
import React, { useState } from "react";
import "./styles.css";
 
export default function App() {
  // defining a user message state

  const [userMsg, setUserMsg] = useState("Start learning React Hooks");

  //function to change the state
  const handleUserMsg = () => {};

  return (
    <div className="App">
      <h1>Hello User</h1>
      {/* using the state  */}
      <h2>{userMsg}</h2>
      <button onClick={handleUserMsg}>Get Started</button>
    </div>
  );
}


```
- Now anywhere we use the `{userMsg}` state in our template, we will expect to output the initial value `Start learning React Hooks`

### Updating the State using the `Setter` function

> The setter function returned by the `useState` hook is responsible for updating the state in react component. 

- Anytime we want to update state in React, we should use the `setter` function, and **not update the state directly**. 
- Meaning, we can not assign a **new value** to a variable in React, and expect the new value to reflect on the UI. We will need to use the `setter` function to assign a new value.

Referencing the code above, when we click on the `Get Started` button, the `handleUserMsg` event handler function will be executed.
In the `handleUserMsg` function's code block, we will now **update the state** by doing the below:

-  We will call the `setUserMsg` function, and then pass it the **new value** we want the `userMsg` to store.

See the code below:

```
  const handleUserMsg = () => {
//updating the state variable
    setUserMsg("Lesson one: React useState Hook");
  };
```
- The `setUserMsg` has now **updated the value** stored in `userMsg`

Now, when we click the `Get Started` button, the `handleUserMsg` function will be executed, and in the function's body, we update the value stored in the `userMsg` . Since a new value has been assigned to the `userMsg` variable, the component will re-render and the browser will display the  **new value** `Lesson one: React useState Hook`

The UI will display the below:

```
Hello User
Lesson one: React useState Hook
```
Below is the updated code:

```
import React, { useState } from "react";
import "./styles.css";

export default function App() {
  // defining a user message state

  const [userMsg, setUserMsg] = useState("Start learning React Hooks");

  //function to update the state

  const handleUserMsg = () => {

//updating the state variable
    setUserMsg("Lesson one: React useState Hook");
  };
  return (
    <div className="App">
      <h1>Hello User</h1>
      {/* using the state  */}
      <h2>{userMsg}</h2>
      <button onClick={handleUserMsg}>Get Started</button>
    </div>
  );
}

``` 

Now using the `useState` hook , we can achieve the following:

- Decide which data or information to display on the UI 
- Update that data or information using the `setter` function provided by the `useState()` hook.

### Adding multiple state variables to the component 

More than one state  (data or information) of as many `data types` can be added to our component using multiple `useState()` calls. This helps us to display vital information on the user interface of our app.

To acheive that, use the syntax below:


```
function MyComponent() {
  const [state1, setState1] = useState(initial1); // first state 
  const [state2, setState2] = useState(initial2); // second state
  const [state3, setState3] = useState(initial3); // third state 
  // ...
}
``` 
Let's display multiple data or information (state) in our app.

```
import React, { useState } from "react";
import "./styles.css";

export default function App() {
// adding multiple states
  const [userName, setUserName] = useState("Emmanuel"); 
  const [posts, setPosts] = useState(7);
  const [showPosts, setShowPosts] = useState(false);

  return (
    <div className="App">
      {/* using the userName state */}
      <h1>Hello {userName}</h1>
      {/* using the  posts state  */}
      <p>You have {posts} articles published </p>
    </div>
  );
}

``` 
The output of the code will be 

```
Hello Emmanuel
You have 7 articles published
``` 
- In the code above, we have display information about the user , and the number of posts published.
- It is a good practice to have multiple state variables, if the state is unrelated.For instance, the `userName` and `posts` state variables are unrelated, so we create multiple state variables.
- If the state variables are related, it will be a good idea to put them in an `object`.

### Using Objects as State variables

The state variable can be of any `data` type. So far, we have used a `string` and a `number` as state variables.
Let's take a look at using `object` as state variables.

```
import React, { useState } from "react";
import "./styles.css";

export default function App() {
//using objects as state variables.
  const [userDetails, setUserDetails] = useState({
    fullName: "Emmanuel Kumah",
    title: "Frontend Developer",
    location: "Ghana",
    bio: "Helping you understand everyline of code"
  });

  return (
    <div className="App">
      <h1>Profile </h1>
      <p>
        <strong>Name:</strong>
        {userDetails.fullName}
      </p>
      <p>
        <strong>Title:</strong>
        {userDetails.title}
      </p>

      <p>
        <strong>location</strong>
        {userDetails.location}
      </p>
      <p>
        <strong>Bio</strong>:{userDetails.bio}
      </p>
    </div>
  );
}

``` 
- The `userDetails` stores an`object`  `{...}`
- In our JSX template we can access the object `values` using the respective `key` Eg. `{userDetails.fullName}`

The output of the above will be:

```
Profile
Name:Emmanuel Kumah

Title:Frontend Developer

location: Ghana

Bio:Helping you understand everyline of code
``` 

-  All our data was stored in an `object` called `userDetails`.
-  We accessed the data stored in the `userDetails` object using the `key:value` pair in JavaScript.
- Our UI will then show the data needed.
- If we want to update the data, we will use the `setUserDetails` function, and update the respective value.

### Updating the state based on previous state

Often, we want to update the state by relying on the value of the previous state. 

For instance:
- We have a `count` state variable initialized to `0`
- When we click on the  `Count me` button, we want to count the number of times the button has been clicked. 
- To achieve this, we need **access to the previous count** to increase it by one.

Let's see an example 


```
import React, { useState } from "react";
import "./styles.css";

export default function App() {
     const [count, setCount] = useState(0);

  // function to increase count
  const handleCount = () => {

//updating the state based on previous value
    setCount((count) => count + 1);
  };
  return (
    <div className="App">
       {/* using the count state  */}
        <p>You have clicked the button {count} times</p>
        <button onClick={handleCount}>Count me</button>
      </div>
    </div>
  );
}

``` 

What is happening in the code above:

1. The `useState()` hook was called, and passed the initial value of `0`. 
2. The two values returned by calling the `useState(0)`  is stored in the `count` and `setCount` variables
3. The inital state value `0` is stored in the `count` variable
4. The `setCount` which is the `setter` function  will update the `count` value 
5. In our JSX template, we display the `count` value like `{count}`.
6. When the component re-renders we will see the value `0` on the screen.

-  To update the `count` value based on the previous value, we need to pass an **updater** function to the `setCount`
- The `updater` function takes the `previous state` and evaluates the `next state`. 

Below is the function to update the state 

```
  // function to increase count
  const handleCount = () => {
    setCount((count) => count + 1);
  };
``` 
- Take note of the `setCount((count) => count + 1)`
- The `(count) => count + 1` is the `updater` function. It is a `callback` function we passed to the `setter` function. 
- When the `setCount` function is executed, it will evaluate the expression passed as arguments
- In the expression, we access the current `count` , increase it value by `1` and returns the value
- So if the current `count` has a value of `0`, on the first click of the button, the value is updated to `1`. 

> Whenever, you want to update the state based on value in  the previous state, remember to pass the `updater` function to the `setter` function.

- Clicking on the `count me` button, we call the `handleCount` function. 
- In the `setCount` puts the `callback` or `updater` function in a queue. 
- During the next render, it wil call the `updater` function take the previous value of   `count` , and add `1`  to it , `count + 1` , and returns the **updated **value.
- On the next click on the button, the `current state` value is now `1`, and we add `1` to the current state, returning a next value of `2`. 

This is what is happening when we click on the `count me` button 3 times.

```
  // function to increase count
  const handleCount = () => {
    setCount((count) => count + 1); // setCount(0 => 1);
    setCount((count) => count + 1); // setCount(1 => 2);
    setCount((count) => count + 1); // setCount(2 => 3);

  };
``` 

- `count => count + 1` will receive `0` as the initial state and return `1` as the next state
- `count => count + 1` will receive `1` as the previous state and return `2` as the next state
- `count => count + 1` will receive `2` as the previous state and return `3` as the next state

### Where to call  the `useState()` hook

Be aware of the following rules when using `useState()` hook:

- Do not use `useState()` in loops, conditions, nested functions , etc
- Use only `useState()` inside functional component or a custom hook
- Call  the `useState()` hook at the top level of the component.

## Recap

In conclusion: 
- In React app, it is a bad practices to update states variables directly like we do in JavaScript
- We should use the `useState` hook to  track, update and manage states in function components 
- The `state variable` can be of any `data type` (`strings`, `numbers`, `boolean`, `objects`)
- The call to the `useState(initialState)` hook returns two values, the `initalState` and a `setter` function
- To update the state use the `setter` function
- When the state is updated, the component will re-render to show the updated state (data) in our UI
- You can have multiple state variables in your component. 

Thanks for taking time to read my article. If you find this article, useful, kindly share it on your social media pages. Any comment or suggestion on the article will be appreciate. 

Written wth love from Ghana. Me daa se (*Thank you*)