DEV Community

Cover image for useState, React State Management Made Simple
Abhijeet kumar
Abhijeet kumar

Posted on

useState, React State Management Made Simple

🤔What is useState in React?

So you've just started learning React or may you just made React frontend using AI and you keep seeing this useState thing everywhere. You started thinking, What the hell is it? Why is it everywhere in my project? So, don't worry we are going to figure this out in dev post.

🧠 First, what is "state"?
Think of state as your component's memory.
A regular JavaScript variable forgets its value every time a component re-renders. State remembers it. That's the whole idea.

// 👎This won't work
let count: number = 0;
count = count + 1;

// 👍This will work
const [count, setCount] = useState<number>(0);
Enter fullscreen mode Exit fullscreen mode

😮The basic syntax

const [state, setState] = useState<Type>(initialState);
Enter fullscreen mode Exit fullscreen mode
  • value → the current state value
  • setValue → the function you call to update it
  • initialValue → what it starts as (a number, string, boolean, array, object — anything!)
  • Type → the TypeScript type of your state (often inferred automatically!)

TypeScript can usually infer the type from the initial value, so useState(0) is the same as useState(0). But being explicit is great practice, especially for complex types.

Example 1: Counter
The classic. Let's build a simple counter.

import useState from "react";
function Counter(){
  const [count, stateCount] = useState<number>(0);
  function handleClick(){
      setCount(count + 1);
  }
  return(
    <div>
     <p> You click me {count} times </p>
     <button onClick={handleClick}> Click me </button>
    </div>
  );
}

export default Counter;
Enter fullscreen mode Exit fullscreen mode

Every time you click the button, setCount updates the value and React re-renders the component with the new count. Simple!

Example 2: Toggle
Toggles are everywhere — dark mode, show/hide menus, open/close modals. Here's the pattern:

import { useState } from "react";

function DarkModeToggle() {
  const [isDark, setIsDark] = useState<boolean>(false);

  return (
    <div style={{ background: isDark ? "#111" : "#fff", padding: "20px" }}>
      <p style={{ color: isDark ? "#fff" : "#111" }}>
        {isDark ? "Dark mode 🌙" : "Light mode ☀️"}
      </p>
      <button onClick={() => setIsDark(!isDark)}>Toggle</button>
    </div>
  );
}

export default DarkModeToggle;
Enter fullscreen mode Exit fullscreen mode

The trick is !isDark — it just flips the boolean each time.

Example 3: Form Input
This one's super common. You want to capture what the user types:

import { useState, ChangeEvent } from "react";

function NameForm() {
  const [name, setName] = useState<string>("");

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    setName(e.target.value);
  };

  return (
    <div>
      <input
        type="text"
        placeholder="Enter your name"
        value={name}
        onChange={handleChange}
      />
      <p>Hello, {name || "stranger"}! 👋</p>
    </div>
  );
}

export default NameForm;
Enter fullscreen mode Exit fullscreen mode

A few things to notice:

  • value={name} keeps the input in sync with state (this is called a controlled input
    )

  • ChangeEvent is the TypeScript type for an input's change event — it tells TS exactly what e looks like

  • e.target.value is the current text in the input

3 Things to Remember

  1. Never mutate state directly
// ❌ Don't do this
count = count + 1;

// ✅ Do this
setCount(count + 1);
Enter fullscreen mode Exit fullscreen mode
  1. State updates trigger a re-render
    Every time you call your setter function, React re-renders that component. That's how your UI stays up to date.

  2. Each component gets its own state
    If you use twice on a page, each one has its own independent count. They don't share state.

  3. Be explicit with types when state can be null

// If the initial value could be null, tell TypeScript!
const [user, setUser] = useState<string | null>(null);
Enter fullscreen mode Exit fullscreen mode

This is where TypeScript really earns its keep — it'll warn you if you try to use user without checking if it's null first.

👋That's it!
useState is honestly one of those things that clicks really fast once you start using it. The key insight is: whenever your UI needs to change based on user interaction, you probably need state.
Start with these three patterns — counter, toggle, form — and you'll have a solid foundation for almost everything. And with TypeScript in the mix, you'll catch bugs before they even happen.

Goodbye Imposter Syndrome!

Top comments (0)