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.

Leave a Comment