Sitemap

State (useState Hook) in React

3 min readMar 3, 2026

--

Press enter or click to view image in full size

State is what makes React applications interactive. Without state, components would only display static content. With state, components can change, respond to user input, and re-render dynamically.

In functional components, we manage state using the useState hook.

What Is State?

State is data that belongs to a component and can change over time.

When state changes, React re-renders the component, and the UI is updated.

State is like the component’s “private memory.”

import { useState } from "react";

function Counter() {
// useState(0) initializes 'count' at 0
const [count, setCount] = useState(0);

return <h2>{count}</h2>;
}
// count is the current state value (the data you want to store)
// setCount - the function to update the state (setter function)

useState

useState is a function provided by React, and it returns: [ currentState, setterFunction ]

To use state, you must import the hook from React as import { useState } from “react”;

  • The current state value: The data you want to store.
  • The setter function: A function used to update the data and trigger a re-render.

How State Triggers a Re-render

When you call the setter function (e.g., setCountin the above example, which Reacts defines internally), React doesn't just change a variable; it schedules a re-render. React calls your component function again, sees the new state value, and updates the DOM to match the new JSX.

Get Nimmikrishnab’s stories in your inbox

Join Medium for free to get updates from this writer.

Never modify the state variable directly (e.g., count = count + 1). React won't know the data changed, and your UI will stay stuck on the old value. Always use the setter function.

Working with Objects and Arrays

State isn’t limited to numbers or strings. However, when working with objects or arrays, you must provide a new copy of the data rather than mutating the existing one. This is typically done using the spread operator (...).

// updating an Object
const [user, setUser] = useState({ name: 'John', age: 25 });

const updateAge = () => {
setUser({ ...user, age: 26 }); // Copy existing user, then overwrite age
};

//Updating an array
const [items, setItems] = useState(['Apple', 'Banana']);

const addItem = () => {
setItems([...items, 'Cherry']); // Create a new array with the old items plus the new one
};
// new state = ['Apple', 'Banana', 'Cherry']

Functional Updates (The PrevState Pattern)

If your new state depends on the previous state value, it is safer to pass a function to the setter. This ensures you are always working with the most up-to-date value, especially during fast, back-to-back updates.

// Safer way to increment
// setCount(prevCount => prevCount + 1);
import { useState } from "react";

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

function increase() {
setCount(prevCount => prevCount + 1);
}

function decrease() {
setCount(prevCount => prevCount - 1);
}

return (
<div>
<h2>Count: {count}</h2>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
);
}

Lifting State Up

In React, state is local to the component. If two sibling components need to share the same state, you must “lift” that state up to their closest common parent. The parent then passes the state down to the children via Props.

import { useState } from "react";

function App() {
// State is lifted up here (common parent)
const [text, setText] = useState("");

return (
<div>
<h2>Lifting State Up Example</h2>

{/* Pass state updater to Input */}
<Input text={text} setText={setText} />

{/* Pass state value to Display */}
<Display text={text} />
</div>
);
}

// Child 1: Updates the state
function Input({ text, setText }) {
return (
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type something..."
/>
);
}

// Child 2: Reads the state
function Display({ text }) {
return <p>You typed: {text}</p>;
}

export default App;

Rules of Hooks

To ensure React can keep track of which state belongs to which component, you must follow these rules:

  • Only call Hooks at the top level: Don’t call useState inside loops, conditions, or nested functions.
  • Only call Hooks from React functions: Use them in functional components or custom hooks, not regular JavaScript functions.

Conclusion

State is a component’s memory for dynamic data. The useState hook lets functional components manage state, and updating it with the setter function triggers a re-render. When the new value depends on the previous one, use functional updates. State updates are asynchronous and may be batched.

--

--