DEV Community

Marvin Roque
Marvin Roque

Posted on

React State: useState Explained Simply

Look, I get it. React state is confusing at first. I spent way too many hours wondering why my components weren't updating properly. Let me save you that headache and break down useState in a way that actually makes sense.

What Even is State?

It's just data that changes. That's it. Think of it like variables that React watches. When they change, your component updates.

Here's a dead-simple counter:

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  // count = the number
  // setCount = how we change it

  return (
    <div>
      <p>Clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        +1
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Updating State (The Way That Actually Works)

I kept messing this up when I started. Here's what not to do:

// 🤦‍♂️ This bit me so many times
const [score, setScore] = useState(0);
setScore(score + 1);
setScore(score + 1);
// Only goes up by 1... why??
Enter fullscreen mode Exit fullscreen mode

Here's how to fix it:

const [score, setScore] = useState(0);
// This actually works
setScore(oldScore => oldScore + 1);
setScore(oldScore => oldScore + 1);
// Now it goes up by 2!
Enter fullscreen mode Exit fullscreen mode

Stuff I Keep Messing Up

Objects Are Tricky

// Don't do what I did:
const [user, setUser] = useState({ name: 'Sam', level: 1 });
user.level = 2;  // Looks right, but doesn't work!

// Do this instead:
setUser({ ...user, level: 2 });  // This works
Enter fullscreen mode Exit fullscreen mode

Checking New Values

// This drove me nuts for hours:
setCount(count + 1);
console.log(count);  // Still the old number!

// What actually works:
setCount(count + 1);
useEffect(() => {
  console.log(count);  // Now we see the new number
}, [count]);
Enter fullscreen mode Exit fullscreen mode

Heavy Calculations

// This slows things down:
const [data, setData] = useState(heavyCalculation());

// Much better:
const [data, setData] = useState(() => heavyCalculation());
Enter fullscreen mode Exit fullscreen mode

Quick Things I Learned The Hard Way

  • Use prev => ... when updating based on old values
  • Never put useState in if statements
  • Keep it simple - split big state objects if they get messy
  • Group related state together in one object

Put It All Together

Here's a real example I use a lot:

function GameScore() {
  const [game, setGame] = useState({
    score: 0,
    highScore: 0
  });

  const addPoints = (points) => {
    setGame(prev => ({
      ...prev,
      score: prev.score + points,
      highScore: Math.max(prev.highScore, prev.score + points)
    }));
  };

  return (
    <div>
      <p>Current: {game.score}</p>
      <p>Best: {game.highScore}</p>
      <button onClick={() => addPoints(10)}>
        Get Points
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

That's pretty much it! Hit me up if you have questions. I'll probably add more examples as I think of them.

Follow if this helped! More real-world React tips coming soon 🚀

Top comments (0)