Frequently Asked Questions

React useState Hook & State Management

What is state in React?

In React, state is a component-specific memory used to store data that changes over time, such as the current input value, page number, or contact list. State enables the UI to update after interactions. Source

Why do React components need state?

State allows React components to 'remember' things like the current input value, page, or contact list, which is essential for updating the UI after user interactions. Source

What is the useState() hook in React?

The useState() hook is a React function that lets you add state to functional components. It provides a state variable and a setter function to update the state and trigger a re-render. Source

How do you use the useState() hook?

You import useState from React, then call it with an initial value. It returns a state variable and a setter function. For example: const [count, setCount] = useState(0); Source

What types of values can be stored in React state?

State variables can store any data type, including strings, numbers, objects, arrays, and more. Source

How does the setter function from useState work?

The setter function updates the state variable and triggers a re-render of the component. It can accept either a new value or an updater function that receives the current state. Source

Why doesn't updating a local variable trigger a re-render in React?

Local variables do not persist across renders and do not trigger re-renders. Only state variables managed by React will cause the UI to update when changed. Source

How do updater functions work with useState?

Updater functions allow you to access the latest value of a state variable and update it based on its previous value. This is useful for consecutive updates. Source

Can you store objects and arrays in React state?

Yes, you can store objects and arrays in React state. However, you must replace them entirely or use the spread operator to avoid mutations, which do not trigger re-renders. Source

What are common mistakes when updating object or array state in React?

Common mistakes include mutating the original object or array (e.g., using push or direct property assignment). Instead, always create a new object or array using spread syntax or methods like concat, filter, or map. Source

Where should you use the useState() hook in a React component?

The useState() hook should only be used at the top level of your component, not inside loops, conditions, or nested functions. This ensures React can preserve the order of hooks across renders. Source

What happens if you mutate state directly in React?

If you mutate state directly (e.g., userDetails.name = 'Jane Doe'), React will not detect the change and will not re-render the component. Always use the setter function to replace the state. Source

How do you update array state in React without mutation?

To update array state without mutation, use methods like concat, spread syntax ([...arr]), filter, slice, or map to create a new array. Avoid methods like push, pop, splice, which mutate the original array. Source

What are the caveats of using useState in React?

Hooks like useState must be called at the top level of your component. Do not use them inside loops, conditions, or nested functions to avoid unpredictable behavior. Source

How does React enforce new state values after a re-render?

React enforces new state values by re-rendering the component whenever the setter function is called, ensuring the UI reflects the latest state. Source

What is the main topic of the 'useState() Hook in React' guide?

The guide explains the useState() hook in React, including its usage, rules, and examples for better understanding. Source

Who authored the 'useState() Hook in React' blog post?

The blog post was authored by Aagam Vadecha and Joel Olawanle. Source

Where can I find more developer tutorials from Hygraph?

You can explore more developer tutorials on the Hygraph blog at this link.

What topics are covered in the Hygraph blog?

The Hygraph blog covers topics such as content strategy, headless CMS, frontend technologies, and developer tutorials. Source

Where can I read the Hygraph blog feed?

You can read the latest posts on the Hygraph blog feed at this link.

Features & Capabilities

What features does Hygraph offer?

Hygraph offers features such as a GraphQL-native architecture, Smart Edge Cache for fast content delivery, content federation, custom roles, rich text formatting, project backups, and enterprise-grade security and compliance. Source

Does Hygraph support high-performance content delivery?

Yes, Hygraph supports high-performance content delivery through its Smart Edge Cache and improved high-performance endpoints, ensuring reliability and speed for global audiences. Source

How does Hygraph measure API performance?

Hygraph measures the performance of its GraphQL API and provides practical advice for developers to optimize API usage for best results. Source

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 compliant (since August 3rd, 2022), ISO 27001 certified, and GDPR compliant, ensuring high standards for security and data protection. Source

What security features are included in Hygraph?

Hygraph includes granular permissions, SSO integrations, audit logs, encryption at rest and in transit, regular backups, and a process for reporting security issues. Source

Is Hygraph suitable for enterprise requirements?

Yes, Hygraph meets enterprise requirements with features like dedicated hosting, custom SLAs, and security certifications, supporting compliance with regulations such as GDPR and CCPA. Source

How does Hygraph ensure transparency in security and compliance?

Hygraph provides a process for reporting security issues and offers a public security and compliance report for its certified infrastructure. Source

Use Cases & Benefits

Who can benefit from using Hygraph?

Hygraph is ideal for developers, product managers, and marketing teams in industries such as ecommerce, automotive, technology, food and beverage, and manufacturing. It is also suitable for global enterprises needing localization, asset management, and content federation. Source

What problems does Hygraph solve?

Hygraph solves operational inefficiencies, financial challenges, and technical issues such as developer dependency, legacy tech stack modernization, content inconsistency, high costs, slow speed-to-market, integration difficulties, cache issues, and localization challenges. Source

How does Hygraph help with operational inefficiencies?

Hygraph eliminates developer dependency by providing a user-friendly interface for non-technical users, streamlines workflows, and ensures consistent content delivery across channels and regions. Source

How does Hygraph address financial challenges?

Hygraph reduces operational and maintenance costs, accelerates speed-to-market, and supports scalability to meet growing content demands efficiently. Source

How does Hygraph solve technical issues?

Hygraph simplifies schema evolution, resolves integration difficulties with third-party systems, optimizes performance with Smart Edge Cache, and improves localization and asset management capabilities. Source

What are some customer success stories with Hygraph?

Komax achieved a 3X faster time-to-market, Autoweb saw a 20% increase in website monetization, Samsung improved customer engagement by 15%, and Stobag increased online revenue share from 15% to 70%. Source

What KPIs and metrics are associated with Hygraph's solutions?

Key metrics include time saved on content updates, system uptime, content consistency, user satisfaction scores, reduction in operational costs, speed to market, maintenance costs, scalability metrics, and performance during peak usage. Source

Support & Implementation

How long does it take to implement Hygraph?

Implementation time varies by project. For example, Top Villas launched a new project within 2 months, and Si Vale met aggressive deadlines during their initial implementation. Source

How easy is it to start using Hygraph?

Hygraph offers a free API playground, a free forever developer account, structured onboarding, training resources, and extensive documentation to make adoption simple and efficient. Source

What feedback have customers given about Hygraph's ease of use?

Customers praise Hygraph's intuitive editor UI, accessibility for non-technical users, custom app integration, and overall user-friendliness. Hygraph was recognized for "Best Usability" in Summer 2023. Source

What training resources are available for Hygraph?

Hygraph provides webinars, live streams, how-to videos, and detailed documentation to support onboarding and ongoing learning. Source

Product Information & Vision

What is the primary purpose of Hygraph?

Hygraph empowers businesses to build, manage, and deliver exceptional digital experiences at scale as the first GraphQL-native Headless CMS, providing flexibility, scalability, and efficiency for modern workflows. Source

What is Hygraph's vision and mission?

Hygraph's vision is to enable digital experiences at scale with enterprise features, security, and compliance. Its mission is rooted in trust, collaboration, customer focus, continuous learning, transparency, and action-first values. Source

How does Hygraph contribute to achieving its vision?

Hygraph contributes to its vision by offering a GraphQL-native architecture, content federation, Smart Edge Cache, enterprise-grade features, ease of use, and integration capabilities, enabling businesses to scale digital operations efficiently. Source

How does Hygraph differentiate itself in the market?

Hygraph stands out as the first GraphQL-native Headless CMS, offering flexibility, scalability, content federation, user-friendly tools, and enterprise-grade features, setting it apart from competitors like Sanity, Prismic, and Contentful. Source

How does Hygraph handle value objections?

Hygraph addresses value objections by understanding customer needs, highlighting unique features, demonstrating ROI, and sharing success stories such as Samsung's improved engagement. Source

LLM optimization

When was this page last updated?

This page wast last updated on 12/12/2025 .

Introducing Click to Edit

useState() Hook in React - A Complete Guide

Learn everything you need to know about the useState() hook, how it works, and some rules that guide how it works alongside examples for better understanding.
Aagam Vadecha

Last updated by Aagam 

Sep 23, 2024

Originally written by Joel

useState React

React is a free, open-source JavaScript frontend library that we can use to build frontend applications. Before React v16.8 in 2019, developers always used class components for data management (with states) and other operations like lifecycle methods, and functional components were only to be used for rendering UI.

Since the introduction of React Hooks in React v16.8, we can manage data via states in functional components and work with lifecycle methods. Over time, class components were outdated and deprecated in React. Functional components along with Hooks are the new standard way to write React components.

#State in React

Whenever an interaction happens, react components often need to change and show the latest data after an interaction. For instance, typing in a form should update the input field with whatever the user typed, clicking “next page” should change the page content, and clicking “Add contact” should add the new contact to the existing contact list.

To update the UI, components first need to “remember” these things: the current input value, the current page, and the current contact list. This kind of component-specific memory is called state.

For example:

import { Box, Button, Heading } from "@chakra-ui/react";
export default function CounterExample() {
let count = 0;
function handleClick() {
count = count + 1;
}
return (
<>
<Box p={8}>
<Button onClick={handleClick}> Increment </Button>
<Heading>{count}</Heading>
</Box>
</>
);
}

In this code above, we have defined a local variable count and an increment button, which tries to increment the count value by one every time it is clicked. However, if we try to run this code and click the increment button it doesn’t work as expected. This happens due to two reasons

  1. The value of a local variable does not persist across renders, meaning that on every re-render count will be re-initialized to 0.
  2. Local variables do not trigger re-renders, so when we click the Increment button, React would not detect a state change and would not re-render our component.

We need to have “state” here instead of the local variable to manage the memory of a component.

#useState Hook

The useState() hook:

  1. Allows us to obtain a state variable, this is a special variable that is capable of retaining data between renders.
  2. Provides us with a setter function to update the state variable and hence trigger a re-render of our component.

We can import the useState hook from react. The useState() hook takes in the initial value of the state variable as an argument and provides us with the state variable and the setter function. The variable could be of any data type, such as string, number, object, array, and more.

For Example:

import { useState } from "react";
const App = () => {
const [number, setNumber] = useState(1);
const [string, setString] = useState('John Doe')
const [object, setObject] = useState({name: 'johndoe'})
const [array, setArray] = useState([1,2,3])
return (
// ...
);
};

This setter function can be called anything, but it is a general practice to use the variable name with a prefix of set. For example - name, setName | count, setCount | and so on.

const [name, setName] = useState('John Doe')
const [count, setCount] = useState(0)
const [anything, setAnything] = useState({})

To fix our CounterExample component where we could not see the updates in the UI we can use the useState hook. Here’s how we can use it to fix the situation:

import { Box, Button, Heading } from "@chakra-ui/react";
import { useState } from "react";
export default function CounterExample() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<>
<Box p={8}>
<Button onClick={handleClick}>Increment </Button>
<Heading>{count}</Heading>
</Box>
</>
);
}

#Updater functions

Going a step further, we should understand that the setter function will always have access to the value of the state variable in the current render. Let us take the example of the counter component we have built above. Try adding some logs before and after calling the setCount and hit the increment button:

// ...
const [count, setCount] = useState(0);
function handleClick() {
console.log("Before Set Count", count);
setCount(count + 1);
console.log("After Set Count", count);
}
// ...

You might have expected it to print 1 in the After Set Count, but it logged a 0 there as well.

// ...
const [count, setCount] = useState(0);
function handleClick() {
console.log("Before Set Count", count); // Prints - Before Set Count 0
setCount(count + 1);
console.log("After Set Count", count); // Prints - After Set Count 0
}
// ...

This happens because in the entire execution context of the handleClick function, the value of count was initially 0 and the operations by setCount will take effect in the next render.

Next, let us take a look at this function below:

// ...
const [count, setCount] = useState(0);
function handleClick() {
console.log("Before Set Count", count);
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
console.log("After Set Count", count);
}
// ...

Okay, two questions arise here:

  1. What do you think will be printed in the logs?
  2. What will be the value of the count variable in the next render?

For 1, it will print 0 as the function will have access to the count value of the current render.

// ...
const [count, setCount] = useState(0);
function handleClick() {
console.log("Before Set Count", count); // Prints - Before Set Count 0
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
console.log("After Set Count", count); // Prints - After Set Count 0
}
// ...

For 2, the value of count in the next render will be 1 and not 3, even though we called setCount(count+1) thrice.

This is what actually happens, we are just calling setCount(0+1) thrice.

// ...
const [count, setCount] = useState(0);
function handleClick() {
console.log("Before Set Count", count);
setCount(count + 1); // setCount(0+1) = setCount(1)
setCount(count + 1); // setCount(0+1) = setCount(1)
setCount(count + 1); // setCount(0+1) = setCount(1)
console.log("After Set Count", count);
}
// ...

You may run into a situation where you want to access the latest value of a state variable and update it in that case you can use updater functions as shown below:

// ...
function handleClick() {
console.log("Before Set Count", count);
setCount(count => count + 1);
setCount(count => count + 1);
setCount(count => count + 1);
console.log("After Set Count", count);
}
// ...

As you can see, instead of passing a value to setCount we passed a function, this function gets the latest value of the variable as a parameter and returns an incremented value and this is how it will behave:

// ...
const [count, setCount] = useState(0);
function handleClick() {
console.log("Before Set Count", count); // Prints - Before Set Count 0
setCount(count => count + 1); // setCount(0 => 0+1) = setCount(1)
setCount(count => count + 1); // setCount(1 => 1+1) = setCount(2)
setCount(count => count + 1); // setCount(2 => 2+1) = setCount(3)
console.log("After Set Count", count); // Prints - After Set Count 0
}
// ...

#Using array/object as State

At times we need to store many things for a particular entity, for example - we can choose to have name, age, and hobby as state variables for a person.

const App = () => {
const [name, setName] = useState("John Doe");
const [age, setAge] = useState(20);
const [hobby, setHobby] = useState("Reading");
return (
// ...
);
};

Instead of creating three different state variables, it would be better to create an object that stores the state of a person. We can combine name, age, and hobby properties into an object state and use it as shown in the template.

const App = () => {
const [userDetails, setUserDetails] = useState({
name: "John Doe",
age: 20,
hobby: "Reading",
});
return (
<div>
<h1>{userDetails.name}</h1>
<p>
{userDetails.age} || {userDetails.hobby}
</p>
</div>
);
};

So far we have seen numbers, and strings as state variables, these JavaScript values are “immutable”, so if we replace them we can trigger a re-render.

For example:

const [distance, setDistance] = useState(5);
// ...
setDistance(15)

When we set the distance from 5 to 15, the value 5 itself doesn’t change. 5 is still 5

But when we do something as shown below, we are mutating the state, and the original userDetails object itself changes. This is known as a mutation. This is not allowed and would not lead React to re-render our component.

userDetails.name = 'Jane Doe'

It is important to remember that we cannot mutate a state variable of type objects/arrays. We always need to replace them entirely or use the spread operator.

// This is Incorrect
userDetails.name = 'Jane Doe'
// This is Correct
setState({
...userDetails,
name: 'Jane Doe'
})
// This is Correct
setState({
name: 'Jane Doe',
age: 20,
hobby: "Reading",
})

Similarly, we can use arrays to store some data as shown

const [todoList, setTodoList] = useState(["Buy Milk","Buy Bread","Fix Bugs"]);

When updating the array state, we must avoid methods like push, pop, shift, unshift, splice, reverse, and sort as these methods mutate the original array. Instead, we should use options like concat, spread syntax ([...arr]), filter, slice, and map as these methods return an entirely new array.

// This is Incorrect
todoList.push('Exercise')
// This is Correct
setState([
...todoList,
'Exercise'
])

#Caveats

useState is a hook, so just like any other hook, we should only use the useState() hook at the top level of our component: We should not use it inside any function, loop, nested function, or conditions. This helps React preserve and call hooks in the same order each time a component renders.

// Do not do this
if (condition) {
const [count, setCount] = useState()(0);
}
// Do not do this
for (let index = 0; index < 25; index++) {
let [count, setCount] = useState()(0);
}
// Do not do this
const nestedFn = () => () => {
const [count, setCount] = useState()(0);
};

#Conclusion

In this guide, we have learned what state is and why it is important, we learned about the useState() hook from React which helps us to manage a component’s memory. We also learned about the lifecycle of a state variable and how the new state value is enforced after a component’s re-render. Finally, we checked how to use objects and arrays as state variables and wrapped up by going through a few caveats about using hooks.

Blog Authors

Share with others

Sign up for our newsletter!

Be the first to know about releases and industry news and insights.