What is the useState Hook in React: A Complete Guide

Published on  

11 min read

What Is The useState() Hook In React: A Complete Guide

In this article, we'll provide you with a comprehensive guide to the useState() hook in React, including what it is, how to use it, and the benefits it provides.

If you're familiar with ReactJS, you may have heard about the useState() hook. Let's get started.

What is React?

Before we dive into the useState() hook, it's essential to understand what React is. React is an open-source JavaScript library that was created by Facebook. It's commonly used for building user interfaces and web applications. React allows developers to build reusable components that can be used throughout an application, making it easier to build and maintain large applications.

React Hooks

React Hooks are a set of functions that were introduced in React 16.8. These functions allow developers to use state and lifecycle methods within functional components, which were previously only available in class components. Hooks allow developers to write more reusable and efficient code, making it easier to manage complex applications.

What is the useState() Hook?

The useState() hook is one of the most commonly used React Hooks. It allows developers to add state to functional components. Before the introduction of Hooks, state could only be used within class components. With the useState() hook, developers can easily manage state in functional components.

How to use state in Class Component and Functional Component?

React has two main types of components, class components, and functional components. Both components can use state, but there are differences in how state is used and managed.

Class components are created by extending the React Component class. They have a state object that is initialized in the constructor method. The state can be updated using the setState() method. Class components have access to the component lifecycle methods, such as componentDidMount(), componentDidUpdate(), and componentWillUnmount(). These methods can be used to manipulate the state based on different events and conditions.

Here is an example of a class component that uses state:

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  incrementCount = () => {
    this.setState(prevState => ({ count: prevState.count + 1 }));
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>Increment Count</button>
      </div>
    );
  }
}

export default Counter;

On the other hand, functional components are created using JavaScript functions. They do not have a constructor method, and state can be managed using the useState() hook. The useState() hook takes an initial state value and returns an array containing the current state value and a function to update the state. The state can be updated by calling the function returned by useState().

Here is an example of a functional component that uses state:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={incrementCount}>Increment Count</button>
    </div>
  );
}

export default Counter;

As you can see, functional components are much simpler and easier to read and maintain than class components. Additionally, they are also faster and more performant than class components. However, class components offer more control and flexibility when it comes to managing state and handling lifecycle events. However, functional components with the useState() hook are the preferred way to manage state in modern React applications due to their simplicity, readability, and performance benefits.

Benefits of the useState() Hook

The useState() hook provides several benefits, including:

  • Easy to use: The useState() hook is easy to use and can be quickly implemented in functional components.
  • Reusability: State can now be used in functional components, making it easier to create reusable components.
  • Simplifies code: The useState() hook simplifies code, making it easier to manage complex applications.

How to Use the useState() Hook

Using the useState() hook is straightforward. Let's break down the usage of useState hook line by line from below example:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

1. Importing the useState

You must first import the useState Hook into our component before we can use it. Import the useState Hook at the top of your component.

import React, { useState } from 'react';

2. Initializing the useState

In our function component, we call useState to initialize our state. useState takes a starting state and returns two values: The current state and a function for updating the state. At the top of the function component, initialize state.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
}

Again, we are destructuring the values returned by useState. The first value, count, represents our current state. The setCount function is used to update our state in the second value. These are variables that can be named whatever you want. Finally, we set the initial state to zero: useState(0)

3. Accessing or reading the state

Below we get the idea how to access the count state as variable. We also can access the state from anywhere within the functional component.

<p>You clicked {count} times</p>

4. Updating the state

When we initialized the useState, we defined a function for updating the state followed by the state variable. In our example the function was setCount

<button onClick={() => setCount(count + 1)}>
  Click me
</button>

To update the state, we can call the function and pass the new value. In our case we incremented the state value using setCount(count + 1).

What Data does the React useState() Hook store?

The useState can hold any data type, which is an advantage over states in a class component, which can only hold an object. A hook, on the other hand, can hold an object, an array, a string, a boolean, or a number.

1. Initializing State as an Array

import React, { useState } from "react";

function CountryList() {
	const [countries, setCountries] = useState(["USA", "UK", "Canada"]);

	return <h1>The countries are {countries.join(", ")}</h1>;
}

2. Initializing State as a String

import React, { useState } from "react";

function StringComponent() {
	const [name, setName] = useState("Rexposed");
    
	return <h1>Thank you for visiting {name} website.</h1>;
}

3. Initializing State as a Boolean

import React, { useState } from "react";

function OpenOrClose() {
	const [isOpen, setIsOpen] = useState(false);

	return <h1>We're ${isOpen ? "Open" : "Closed"}</h1>;
}

4. Initializing State as a Number

import React, { useState } from "react";

function Counter() {
	const [count, setCount] = useState(2023);

	return <h1>Current year is: {count}</h1>;
}

5. Initializing State as an Object

Let's have a look of a complete Sign-in Form component where we used state as an Object:

import React, { useState } from "react";

function LoginForm() {
	const [values, setValues] = useState({
		email: "",
		password: "",
		remember: false,
	});

	function handleChange(event) {
		const key = event.target.name;
		const value = event.target.type === "checkbox" ? event.target.checked : event.target.value;

		setValues((previousValues) => {
			return {
				...previousValues,
				[key]: value,
			};
		});
	}

	function handleSubmit() {
		// do your stuffs
	}

	return (
		<form onSubmit={handleSubmit}>
			<input
				type="email"
				name="email"
				value={values.email}
				onChange={handleChange}
			/>
			<input
				type="password"
				name="password"
				value={values.password}
				onChange={handleChange}
			/>
			<label htmlFor="remember">
				<input
                    id="remember"
					name="remember"
					type="checkbox"
					checked={values.remember}
					onChange={handleChange}
				/>
				<span>Remember Me</span>
			</label>
			<button type="submit">Submit</button>
		</form>
	);
}

The object-based state is a bit complicated, but the states initialization is explained below. It would be much more difficult to manage the data if we defined three separate states as shown below. Consider what would happen if we had to include more field in the form.

const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [remember, setRemember] = useState(true)

We can group similar things together using an initial state object.

const [values, setValues] = useState({
  email: "",
  password: "",
  remember: false,
});

Then we can create a simple function to update specific key value inside the state object.

function handleChange(event) {
	const key = event.target.name;
	const value = event.target.type === "checkbox" ? event.target.checked : event.target.value;

	setValues((previousValues) => {
		return {
			...previousValues,
			[key]: value,
		};
	});
}

6. Initializing State as a Function

In a situation where you need to perform a calculation, which is best done within a function. A function that returns a value can be used to initialize a state.

import React, { useState } from "react";

const calculation = () => {
	let value = 50;
	const newValue = (50 % 10) * 10 - value;
	return newValue;
};

function YourComponent() {
	const [value, setValue] = useState(() => calculation());
	
	return (
		<p>{value}</p>
	);
}

Important Things to Know When Using useState() Hook

  • useState (or any other hook) can only be used within a function component.
  • You can not initialize useState inside a loop, if-else, nested function, or any other conditional blocks. It should be at the very top and inside the functional component without any unnecessary checks.
// Wrong

function Component() {
	if (true) {
		const [count, setCount] = useState(0);
	}
}
  • You can not use useState in a Class-Based components.
  • When we update the state, the component re-renders each time.
  • You cannot update the state directly, like this:
// Wrong

function incrementCount() {
	count = count + 1;
}

To use useState effectively, we must change and mutate the state variable based on its initial state, and we must avoid unexpected rendering. To accomplish this, we must pass a previous state parameter to the function and then mutate the state variable based on that. Confused? Let's get started with some code!

setCount(count + 1)

Should be:

setCount(prevState => prevState + 1)

Here, prevState ensures that we always get the current value of count, which is a better and recommended way to write hooks!

Conclusion

The useState() hook is a powerful tool that can be used to manage state in functional components. It provides several benefits, including reusability, simplicity, and ease of use. We hope this article has provided you with a comprehensive guide to the useState() hook in React.

If you're interested in learning more about React, check out our comprehensive guide to React Hooks. And for more React-related content, be sure to check out our React specific articles.

TAGS:

About the Author

Rexposed Staff

Was this helpful?