Why your button doesn't update, your form loses data, and how to fix it.
State is the current situation of your app at any given moment. Is the menu open or closed? What did the user type in the search box? Is the user logged in or logged out? Which tab is selected? All of those are state.
Examples of state in everyday apps:
Which post you're viewing, whether you liked it, the comment you're typing
Amazon
What's in your cart, your shipping address, which filter is selected
Google Docs
The text you've typed, whether bold is on, who else is editing
Spotify
Which song is playing, the volume level, whether shuffle is on
Your app needs to remember things while people use it. Without state, every single click would reset everything back to square one. The form would go blank. The menu would close. The cart would empty.
Analogy:Imagine a waiter with no memory. You order a coffee, they walk to the kitchen, and by the time they arrive they've forgotten what you said. That's an app without state. State is the notepad the waiter writes your order on.
The simplest kind of state. One component remembers one thing. React's useState is the tool for this.
A variable that says "open" or "closed". Clicking the hamburger icon flips it.
A number that starts at 0 and goes up by 1 every time someone clicks a button.
A piece of text that updates every time the user types a character in a text box.
ADD A TOGGLE
"Add a toggle button to the navbar that shows and hides the mobile menu. Use useState to track whether the menu is open or closed. When the user clicks the hamburger icon, toggle the menu visibility."
This is the number one beginner confusion. You change a variable, but nothing happens on screen. The page looks exactly the same.
The mistake
Changing a regular JavaScript variable (like count = count + 1) does not tell React to re-draw the screen. React has no idea you changed anything.
The fix
Use the setter function from useState (like setCount(count + 1)). This tells React: "Hey, something changed — please update the screen."
Analogy:Changing a recipe in your head doesn't change what the kitchen cooks. You have to actually tell the chef. setState is how you tell the chef.
Sometimes a parent component has state that a child component needs to display. Props are how you pass that data down. The child can readthe data but can't change it directly.
Analogy:A manager gives instructions to employees. The employees follow the instructions but don't rewrite them. If something needs to change, the employee tells the manager, and the manager updates the instructions for everyone.
PASS DATA BETWEEN COMPONENTS
"I have a parent component that tracks the selected tab. Pass the selected tab and a function to change it as props to a TabBar child component. Make sure clicking a tab in the child updates the parent's state."
When multiple pages or distant components need the same data, you need global state. Common examples: the logged-in user, a shopping cart, or a light/dark theme preference.
Built into React. Good for simple cases like theme or auth. Can get messy for complex data.
Built-inTiny, fast, simple. The most popular choice for React apps that need global state without complexity.
Most PopularThe original global state library. Powerful but heavier. Still common in large enterprise apps.
EnterpriseRule of thumb
If 3 or more componentsthat aren't parent-child need the same data, go global. Otherwise, keep it local and pass it down with props.
ADD GLOBAL STATE
"Share the logged-in user's data across all pages in my Next.js app. Use Zustand (or React Context if you prefer) to create a global auth store that any component can read. Include the user's name, email, and a logout function."
Not all state lives in the browser. Data stored in a database — like user profiles, blog posts, or product listings — is server state. It's different from UI state because it persists even after the user closes the browser.
UI State (browser)
Server State (database)
Forms are the most state-heavy part of any app. Every text input, checkbox, and dropdown has its own state. See our Forms & Validation guide for the full picture.
Two approaches to form state:
Controlled
React tracks every keystroke. You always know what's in the input. Best for forms that need real-time validation or depend on each other (like "confirm password").
Uncontrolled
The browser tracks the input and you grab the value when the form is submitted. Simpler, less code, fine for basic forms.
CREATE A FORM WITH STATE
"Create a contact form with fields for name, email, and message. Use useState to track each field's value. Show a validation error if the email is invalid. When submitted, log the form data and clear all fields."
Storing too much in state
Only put things in state that change over time and affect what the user sees. Constants, calculations, and data you can derive from other state don't need their own state.
Duplicating state
Don't store the same data in two places. Pick one source of truth and derive everything else from it.
Not lifting state up
If two sibling components need the same state, move it to their shared parent and pass it down as props.
Mutating state directly
Never change an array or object in state directly (like push or assignment). Always create a new copy. Tell your AI tool: "update this state without mutating the original."
Putting server data in useState
Data from your database should be fetched with server components or a data-fetching library, not manually stored in useState.
The shopping list needs to be visible on every page, the measurement toggle only matters on the recipe page, and recipes come from your database.
Build this with AI
"I'm building a recipe app in Next.js. I need: (1) local state for the measurement toggle on the recipe page, (2) global state using Zustand for the shopping list so it's accessible from any page, and (3) the recipes themselves fetched from my database as server state. Set up all three kinds of state with this structure."
Copy-paste these prompts into your AI tool to add state to your app.
ADD A TOGGLE
"Add a toggle for dark mode to my app. Use useState to track whether dark mode is on or off. When the user clicks the toggle, switch the theme and save their preference to localStorage so it persists on refresh."
FORM WITH STATE
"Create a multi-step signup form with state for each step. Track the current step number, form data for all fields across steps, and validation errors. Include a progress bar and back/next buttons."
GLOBAL AUTH STATE
"Share the user's login state across all pages using Zustand. Create a useAuthStore with the user object, isLoggedIn boolean, login function, and logout function. Show the user's name in the navbar and redirect to login if not authenticated."
FIX STATE BUG
"My component shows stale data — when I click the button, nothing updates on screen. I think I'm setting state incorrectly. Can you review my component and fix the state update so the UI reflects the change immediately?"