devnotes.

State with useState & Handling Events

State is data that changes over time and, when updated, causes React to re-render the component. The useState hook is the primary way to add state to a function component.

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // [value, setter] pair

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

Rules of state

  • Never mutate state directly (count++ on its own does nothing useful) — always call the setter function.
  • State updates are asynchronous and batched; React groups multiple setState calls in the same event handler into a single re-render.
  • Each component instance has its own independent state.

Functional updates

When the new state depends on the previous state, pass a function to the setter instead of a value — this avoids bugs with stale state, especially with batching:

// risky if count changes multiple times before re-render
setCount(count + 1);

// safe: always uses the latest state
setCount(prev => prev + 1);

State with objects and arrays

Because React compares state by reference, always create a new object/array instead of mutating the existing one:

const [user, setUser] = useState({ name: 'Rahim', age: 20 });

// wrong — mutates existing object, React won't detect the change
user.age = 21;

// correct — spread the old object, override what changed
setUser(prev => ({ ...prev, age: 21 }));

const [items, setItems] = useState(['a', 'b']);
setItems(prev => [...prev, 'c']);              // add
setItems(prev => prev.filter(i => i !== 'a')); // remove

Handling events

React wraps native DOM events in a cross-browser SyntheticEvent. Handlers are passed as functions, not strings, and use camelCase:

function LoginForm() {
  const [email, setEmail] = useState('');

  function handleSubmit(e) {
    e.preventDefault(); // stop the default full-page reload
    console.log('Submitting:', email);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <button type="submit">Log in</button>
    </form>
  );
}

Common event props: onClick, onChange, onSubmit, onMouseEnter, onKeyDown, onFocus, onBlur.

React useState Hook and Event Handling | DevNotes