React Native Props and State
Props and state are the two systems that control what a component shows on screen. Props pass data into a component from outside. State stores data that lives inside a component and changes over time. Understanding both unlocks the full power of React Native.
The Difference in One Picture
┌─────────────────────┐
PROPS │ Component │
(from parent) ────►│ │
name="Jane" │ Displays data │
age={28} │ Reacts to changes │
│ │
STATE │ count: 0 ──► 1 ──► 2
(internal) │ (changes on tap) │
└─────────────────────┘
Think of a vending machine. Props are the selections you push in from outside (which item you want). State is the internal count of how many items remain — it changes without you touching it from outside.
Props — Data Flowing In
Props (short for properties) are values you pass to a component when you use it. The component uses those values to decide what to display.
Creating a Component That Accepts Props
// Define the component
function Greeting({ name, age }) {
return (
<View>
<Text>Hello, {name}!</Text>
<Text>You are {age} years old.</Text>
</View>
);
}
// Use it with different props
<Greeting name="Jane" age={28} />
<Greeting name="Alex" age={35} />
Screen Output: ┌──────────────────────┐ │ Hello, Jane! │ │ You are 28 years old.│ ├──────────────────────┤ │ Hello, Alex! │ │ You are 35 years old.│ └──────────────────────┘
Props Are Read-Only
A component cannot change its own props. Props flow one way — from parent to child. The parent decides the values. The child only reads them. This one-way data flow keeps your app predictable.
Default Props
You can set a default value for a prop so the component works even when the parent does not pass that prop.
function Greeting({ name = 'Friend' }) {
return <Text>Hello, {name}!</Text>;
}
// Passes name → shows "Hello, Jane!"
<Greeting name="Jane" />
// No name passed → shows "Hello, Friend!"
<Greeting />
State — Data That Changes
State stores values that change during the life of a component. When state changes, React Native automatically re-renders the component to show the new values. You create and manage state using the useState hook.
useState Hook
import { useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
export default function Counter() {
const [count, setCount] = useState(0);
// ↑ ↑ ↑
// current function to initial
// value update it value
return (
<View style={{ alignItems: 'center', marginTop: 50 }}>
<Text style={{ fontSize: 48 }}>{count}</Text>
<TouchableOpacity onPress={() => setCount(count + 1)}>
<Text>Tap to Increase</Text>
</TouchableOpacity>
</View>
);
}
Flow when user taps: ┌─────────────────────────────────────────┐ │ User taps "Tap to Increase" │ │ │ │ │ ▼ │ │ setCount(count + 1) runs │ │ │ │ │ ▼ │ │ count changes from 0 to 1 │ │ │ │ │ ▼ │ │ Component re-renders │ │ │ │ │ ▼ │ │ Screen now shows "1" │ └─────────────────────────────────────────┘
Never Modify State Directly
Always use the setter function to change state. Modifying the variable directly does not trigger a re-render — the screen will not update.
// ✗ WRONG — screen will not update count = count + 1; // ✓ CORRECT — triggers re-render setCount(count + 1);
State with Objects
State can hold any JavaScript value — numbers, strings, booleans, arrays, or objects.
const [user, setUser] = useState({ name: 'Jane', loggedIn: false });
// Update a property — always create a new object
setUser({ ...user, loggedIn: true });
// ↑ spread old values, then override loggedIn
The spread operator ...user copies all existing properties. You then override only the property that changed. This pattern keeps React Native from missing your update.
Props + State Together — A Reusable Like Button
// Child component: accepts a label via props, manages liked state internally
function LikeButton({ label }) {
const [liked, setLiked] = useState(false);
return (
<TouchableOpacity onPress={() => setLiked(!liked)}>
<Text style={{ color: liked ? 'red' : 'grey' }}>
{liked ? '❤️' : '🤍'} {label}
</Text>
</TouchableOpacity>
);
}
// Parent uses it twice with different labels
<LikeButton label="Post" />
<LikeButton label="Comment" />
Before tap: 🤍 Post 🤍 Comment After tap 1: ❤️ Post 🤍 Comment ← only Post liked After tap 2: ❤️ Post ❤️ Comment ← both liked
Each LikeButton has its own separate state. Tapping one does not affect the other. This is the power of encapsulated component state.
Lifting State Up
When two sibling components need to share state, move that state to their common parent. The parent holds the state and passes it down as props.
Parent (holds count state) ├── DisplayComponent (receives count as prop) └── ButtonComponent (receives setCount as prop)
Summary
Props pass read-only data from parent to child. State holds data that changes inside a component. Use useState to create state. Always use the setter function to update state. Together, props and state determine exactly what every component on screen shows at any moment.
