Prerequisites
Before working with useState, it is helpful to understand:
- JavaScript fundamentals
- ES6 syntax, including destructuring and the spread operator
- React functional components
- JSX
- Basic event handling in React
What Is useState?
useState is a React Hook that lets a functional component store a value and update that value over time. When the setter function is used, React schedules a re-render so the component can display the latest state.
The basic syntax is:
|
JavaScript const [state, setState] = useState(initialValue); |
For example:
|
JavaScript import { useState } from "react"; |
In this example:
- count is the current state value.
- setCount is the setter function used to request a state update.
- 0 is the initial value.
- Each click requests a new count value, and React re-renders the component with the updated state.
Why Is useState Important?
A React application frequently needs to respond to user actions. A user might enter a name, add a record, search for information, select a filter, or show and hide part of the interface. State gives the component a way to remember those changing values.
Common use cases include:
- Form inputs
- Counters and numeric values
- Lists of data
- Search fields
- Filters
- Toggle buttons
- Edit modes
- Showing or hiding UI elements
How State Updates Flow Through a React Component
A simplified state-update flow looks like this:
- The user interacts with the UI.
- An event handler runs.
- The event handler calls a state setter.
- React schedules a re-render.
- The component renders with the new state.
- The UI reflects the updated value.
Important: calling a state setter does not immediately change the current state variable inside the running event handler. The updated value is available during the next render.
Managing Arrays with useState
State can hold arrays and objects, not just strings and numbers. For example, a dashboard might maintain a list of records that users can add to or remove from.
An array can be initialized like this:
|
JavaScript const [students, setStudents] = useState([ |
Here, students contains the current array and setStudents is used to request changes to that array. The same pattern applies to dashboards, inventory lists, task lists, and other data-driven interfaces.
Adding Data to State
When adding an item to an array in state, create a new array rather than modifying the existing array directly.
|
JavaScript const newStudent = { |
The spread operator creates a new array containing the previous items and the new item. The functional update form is especially useful when the next state depends on the previous state.
Removing Data from State
The filter() method can create a new array without the item that should be removed.
|
JavaScript setStudents((prevStudents) => |
This returns every student except the one with ID 2 and avoids directly mutating the existing state array.
Managing Form Inputs
Forms are one of the most common use cases for useState. Each input can be connected to a state value, creating a controlled input.
|
JavaScript const [name, setName] = useState(""); |
A state value can then be connected to an input:
|
JavaScript <input |
Whenever the user changes the input, the event handler calls setName(). React then renders the input with the latest state value.
useState and Search Functionality
A search field can also be managed with state:
|
JavaScript const [search, setSearch] = useState(""); |
The search value can then be used to calculate a filtered list:
|
JavaScript const filteredStudents = students.filter((student) => |
Because the component re-renders when search changes, the filtered result can update immediately as the user types.
Common Mistakes to Avoid
1. Directly Modifying State
Avoid mutating an existing array:
|
JavaScript students.push(newStudent); |
Instead, create a new array and update state:
|
JavaScript setStudents((prevStudents) => [ |
2. Using Unclear State Names
Prefer names that describe the value and its setter:
|
JavaScript const [search, setSearch] = useState(""); |
Avoid unclear names such as:
|
JavaScript const [x, setX] = useState(""); |
Clear names make code easier to read, review, debug, and maintain.
3. Forgetting to Import useState
The Hook must be imported before it is used:
|
JavaScript import { useState } from "react"; |
4. Using the Current Value When the Next Value Depends on Previous State
When the next state depends on the previous state, prefer the functional update form. This is especially useful when multiple updates may be scheduled together.
|
JavaScript setCount((previousCount) => previousCount + 1); |
Best Practices for Using useState
- Use meaningful names for state variables and setter functions.
- Do not directly mutate arrays or objects stored in state.
- Use the functional update form when the next state depends on the previous state.
- Keep state focused on values that actually change over time.
- Keep related state values organized and avoid unnecessary duplication.
- Avoid storing values in state when they can be calculated from existing state or props.
- Keep state local to the component when it is only needed there; use broader state management only when shared state is actually required.
- Keep event handlers focused so state transitions remain easy to understand.
When Should You Use useState?
useState is a good choice when a component needs to remember a value that changes as users interact with the interface. Typical examples include:
- A form field that changes as the user types
- A selected tab or filter
- An expanded or collapsed section
- A list that users can add to or remove from
- A search query and its derived results
- A counter or other local UI value
When useState Is Not Enough
useState is component-level state. If many unrelated components need to read and update the same state, lifting state to a common parent, using Context, or adopting a dedicated state-management library may be more appropriate.
The goal is not to move every value into global state. Keep state as close as practical to the components that own and use it.
Real-World Applications
- Dashboards — managing filters, selections, and interactive data
- E-commerce applications — managing cart items, quantities, and product filters
- Task applications — adding, editing, completing, and removing tasks
- Contact forms — managing user-entered values and validation state
- Search interfaces — handling search queries and filtered results
- Administrative applications — managing selected records, edit modes, and form values
Key Takeaways
- useState lets functional components remember and update changing values.
- It returns the current state value and a setter function.
- State updates cause React to render the component again with the new state.
- Arrays and objects in state should be updated without directly mutating the existing value.
- Functional state updates are useful when the next value depends on the previous value.
- Not every calculated value needs to be stored in state.
- useState is ideal for local component state; shared application state may require a different approach.
Conclusion
useState is one of the most important concepts for developers learning React. It provides a simple way for components to remember changing values and keep the user interface synchronized with user interactions.
By applying useState to forms, lists, search, filters, and other interactive features, developers can understand the core relationship between events, state updates, rendering, and UI changes.
Once these fundamentals are clear, concepts such as useEffect, useReducer, Context, and more advanced state-management patterns become easier to understand.
Recent Posts
-
Aug 22 2026
-
Aug 22 2026
-
Aug 22 2026