React Hooks Explained: useState( )
Tags: react, javascript, hooks
Published: 2021-06-27 20:34:36

Original Interactive Post Link => https://webbrainsmedia.com/blogs/react-hooks-explained-useState

Nowadays, managing state is the most crucial part in any application's architecture. Most applications behaviour depends on the values of states defined in them, So understanding how to manage it efficiently becomes very important. Before hooks introduction in React version 16.8, the only way to use state in your application is through class component. But now with the help of `useState` hook we can manage state in our functional components too. So, in this article we will be learning everything that we need to know about `useState` to get started with stateful functional components.

## Comparing State Management in classes and functions

Lets start by understanding the use of `useState` hook by looking at an example of a simple counter application written using React's functional component.

```jsx
import React, { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);
  const [msg, setMsg] = useState('Use the below button to increase the count');

  return (
    <div>
      <p>Counter: {count}</p>
      <p>{msg}</p>
      <button onClick={() => setCount(count + 1)}>Count</button>
    </div>
  );
}
```

For comparison, lets also rewrite it into a class component.

```jsx
import React, { Component } from 'react';
export class CounterClass extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      msg: 'Use the below button to increase the count',
    };
  }

  render() {
    return (
      <div>
        <p>CounterClass: {this.state.count}</p>
        <p>{this.state.msg}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Count
        </button>
      </div>
    );
  }
}
```

Okay now lets compare each aspect one by one.

## Defining initial state

In a class component, initial state is defined as an object inside the constructor containing all the state for the component.

```jsx
constructor(props) {
  super(props);
  this.state = {
    count: 0,
    msg: 'Use the below button to increase the count',
  };
}
```

But in a functional component, we define the initial state by passing it as an argument in the `useState` hook.

```jsx
useState(initialState);
```

The return value of `useState` hook is an array containing the current state and a function to update the value of current state.

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

Now, like in a class component we can define all state for a component in a single `useState` hook.

```jsx
const [state, setState] = useState({
  count: 0,
  msg: 'Use the below button to increase the count',
});
```

But it is a recommended practice to use individual `useState` hook for managing each state. As it is cleaner and easier to maintain.

```jsx
const [count, setCount] = useState(0);
const [msg, setMsg] = useState('Use the below button to increase the count');
```

Now, there can be situations where the initial state you are defining may require time to get resolve. Passing this as initial state in `useState` hook can slow down the whole application. As you know, in functional components the initial state is declared in the render function and its value updates at every render. This is not a problem in class component as the initial state is defined in the constructor which is called only once at the start.

But there is a solution, `useState` also take function as the argument. the `useState` will run this function only once when the component is rendered first time. We can pass the function in `useState` like this

```jsx
useState(() => {
  // Some heavy computation task
});
```

## Updating the State

In class component, we can update the count by calling `this.setState`.

```jsx
this.setState({ count: this.state.count + 1 });
```


Or by returning the updated value of count from a function in `this.setState`.

```jsx
this.setState((prevState) => {
  return { count: prevState.count + 1 };
});
```

In functional components, as we are using individual `useState` for each state. We can easily update the value of count by calling the `setCount` function like this

```jsx
setCount(count + 1);
```

But if you are depending on the previous state for updating to new state. It is recommended to use the function in `setState` like this

```jsx
setCount((prevCount) => prevCount + 1);
```

The reason behind this is say you want to update the state two times in a function and you try to do it like this

```jsx
export function Counter() {
  const [count, setCount] = useState(0);
  const [msg, setMsg] = useState('Use the below button to increase the count');

  return (
    <div>
      <p>Counter: {count}</p>
      <p>{msg}</p>
      <button
        onClick={() => {
          setCount(count + 1);
          setCount(count + 1);
        }}
      >
        Count
      </button>
    </div>
  );
}
```

But you will see that the `count` value is still updating by one. This is because the `count` value in the `setCount` is the same when we render our functional component and `count` value doesn't change inside of the function from where it is called. So, in the above code the `count` value is same in both `setCount`, overriding eachothers value resulting in value of `count` increased by just one.

Now, if we use the function in `setCount`. We can get the desired result as the updated `count` value gets stored in the `prevCount` and we can use the `prevcount` to correctly update the value of `count` inside the function.

```jsx
export function Counter() {
  const [count, setCount] = useState(0);
  const [msg, setMsg] = useState('Use the below button to increase the count');

  return (
    <div>
      <p>Counter: {count}</p>
      <p>{msg}</p>
      <button
        onClick={() => {
          setCount((prevCount) => prevCount + 1);
          setCount((prevCount) => prevCount + 1);
        }}
      >
        Count
      </button>
    </div>
  );
}
```

Lastly, if you are using the single `useState` hook to manage all states like this

```jsx
const [state, setState] = useState({
  count: 0,
  msg: 'Use the below button to increase the count',
});
```

You need to remember that when updating only the value of `count`. Unlike `this.setState`, `setState` will overwrite the whole `state` object to the new object having only value of `count`. You can see in the output of the code below that after clicking the count button the message will get dissappear.

```jsx
export function Counter() {
  const [state, setState] = useState({
    count: 0,
    msg: 'Use the below button to increase the count',
  });

  return (
    <div>
      <p>Counter: {state.count}</p>
      <p>{state.msg}</p>
      <button onClick={() => setState({ count: 1 })}>Count</button>
    </div>
  );
}
```

In order to avoid this you will need to pass the old state with the new state in `setState`.

```jsx
export function Counter() {
  const [state, setState] = useState({
    count: 0,
    msg: 'Use the below button to increase the count',
  });

  return (
    <div>
      <p>Counter: {state.count}</p>
      <p>{state.msg}</p>
      <button
        onClick={() =>
          setState((prevState) => {
            // Expanding prevState object using spread operator
            return { ...prevState, count: 1 };
          })
        }
      >
        Count
      </button>
    </div>
  );
}
```

## Conclusion

`useState` provides a cleaner and a maintainable way to manage states in an application. After reading this article you are ready to start using `useState` in your react projects like a pro.

Original Interactive Post Link => https://webbrainsmedia.com/blogs/react-hooks-explained-useState