← All courses

State & the useState Hook

🗓 May 31, 2026 ⏱ 2 min read

Props vs state

You’ve seen props (data passed in, read-only). State is data a component owns and can change over time — a counter, the text in a field, whether a menu is open. When state changes, React re-renders the component to show the new value.

useState

The useState hook adds state to a function component. It returns the current value and a function to update it.

import { useState } from 'react';
import { View, Text, Button } from 'react-native';

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

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Add" onPress={() => setCount(count + 1)} />
    </View>
  );
}

const [count, setCount] = useState(0) reads as: “count is the value, setCount changes it, starting at 0”.

The golden rule: never mutate state directly

Always use the setter function. Changing the variable directly won’t re-render the UI.

count = count + 1;       // ❌ wrong — UI won't update
setCount(count + 1);     // ✅ correct

Updating based on the previous value

When the new value depends on the old one (especially in quick succession), pass a function to the setter to avoid bugs:

setCount(prev => prev + 1);   // safest way to increment

State with objects and arrays

React replaces state, it doesn’t merge it, so create a new object/array instead of editing the old one:

const [user, setUser] = useState({ name: '', age: 0 });
setUser(prev => ({ ...prev, name: 'Anand' }));   // copy + change one field

const [items, setItems] = useState([]);
setItems(prev => [...prev, newItem]);            // add without mutating

A practical example: a text input

const [text, setText] = useState('');

<TextInput value={text} onChangeText={setText} placeholder="Type..." />
<Text>You typed: {text}</Text>

This “controlled input” pattern keeps your state and the field perfectly in sync.

Common mistakes

  • Mutating state directly instead of using the setter.
  • Editing an object/array in place instead of creating a new copy.
  • Expecting state to update instantly — it applies on the next render, not the same line.
Summary: useState gives a component changeable data. Always update via the setter (use the prev => form when based on the old value), and create new copies for objects/arrays rather than mutating them.