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
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
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
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
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
State variables can store any data type, including strings, numbers, objects, arrays, and more. Source
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
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
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
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
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
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
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
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
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
React enforces new state values by re-rendering the component whenever the setter function is called, ensuring the UI reflects the latest state. Source
The guide explains the useState() hook in React, including its usage, rules, and examples for better understanding. Source
The blog post was authored by Aagam Vadecha and Joel Olawanle. Source
You can explore more developer tutorials on the Hygraph blog at this link.
The Hygraph blog covers topics such as content strategy, headless CMS, frontend technologies, and developer tutorials. Source
You can read the latest posts on the Hygraph blog feed at this link.
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
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
Hygraph measures the performance of its GraphQL API and provides practical advice for developers to optimize API usage for best results. Source
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
Hygraph includes granular permissions, SSO integrations, audit logs, encryption at rest and in transit, regular backups, and a process for reporting security issues. Source
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
Hygraph provides a process for reporting security issues and offers a public security and compliance report for its certified infrastructure. Source
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
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
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
Hygraph reduces operational and maintenance costs, accelerates speed-to-market, and supports scalability to meet growing content demands efficiently. Source
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
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
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
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
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
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
Hygraph provides webinars, live streams, how-to videos, and detailed documentation to support onboarding and ongoing learning. Source
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
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
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
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
Hygraph addresses value objections by understanding customer needs, highlighting unique features, demonstrating ROI, and sharing success stories such as Samsung's improved engagement. Source
This page wast last updated on 12/12/2025 .
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.
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
We need to have “state” here instead of the local variable to manage the memory of a component.
The useState() hook:
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></>);}
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 0setCount(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:
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 0setCount(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 0setCount(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}// ...
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 IncorrectuserDetails.name = 'Jane Doe'// This is CorrectsetState({...userDetails,name: 'Jane Doe'})// This is CorrectsetState({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 IncorrecttodoList.push('Exercise')// This is CorrectsetState([...todoList,'Exercise'])
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 thisif (condition) {const [count, setCount] = useState()(0);}// Do not do thisfor (let index = 0; index < 25; index++) {let [count, setCount] = useState()(0);}// Do not do thisconst nestedFn = () => () => {const [count, setCount] = useState()(0);};
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
Learn about the best CMS options for your Vue.js projects.
Discover 7 top CMS options for Angular apps, with tips on choosing a headless CMS that delivers performance, flexibility, and a great developer experience.
Choosing the right CMS for Astro can make or break your site's performance and workflow. We've narrowed down the best CMS options based on scalability, price and how well they integrate with Astro, so you can find the perfect fit for your project.