Blog
3 min read

React Props Explained: Passing Data Between Components

Props are how a React component receives data from its parent — like arguments to a function. How to pass and read them, destructuring and defaults, passing functions and children, props vs state, and the common mistakes that cause bugs.

React apps are built from components — reusable pieces of UI like a button, a card or a page. Props (short for properties) are how you pass information into a component. (What is React?)

The simplest way to think about it: a component is a function, and props are its arguments.

A first example

function Greeting(props) {
  return <h1>Hello, {props.name}!</h1>
}

export default function App() {
  return (
    <>
      <Greeting name="Ada" />
      <Greeting name="Grace" />
    </>
  )
}

name="Ada" passes a prop. Inside Greeting, it arrives as props.name. Same component, different data, different output.

Destructuring (what you'll usually see)

Instead of writing props. everywhere, most code unpacks the props in the function signature:

function Greeting({ name, excited }) {
  return <h1>Hello, {name}{excited ? '!' : '.'}</h1>
}

<Greeting name="Ada" excited />

A prop with no value (excited) is true.

Passing different types

Strings go in quotes; everything else goes in curly braces:

<ProductCard
  title="Desk lamp"
  price={39.99}
  inStock={true}
  tags={['lighting', 'office']}
  onAddToCart={() => addItem(42)}
/>

Default values

function Button({ label = 'Save', variant = 'primary' }) {
  return <button className={variant}>{label}</button>
}

Passing functions: how children talk to parents

Props only flow down, from parent to child. To let a child tell its parent something happened, pass a function:

function Counter() {
  const [count, setCount] = useState(0)
  return <IncrementButton onIncrement={() => setCount(count + 1)} />
}

function IncrementButton({ onIncrement }) {
  return <button onClick={onIncrement}>+1</button>
}

The child calls onIncrement; the parent updates its state. (React useState explained)

The special children prop

Whatever you put between a component's tags arrives as children:

function Card({ children }) {
  return <div className="card">{children}</div>
}

<Card>
  <h2>Pricing</h2>
  <p>Simple and fair.</p>
</Card>

This is how layout components and wrappers work.

Props vs state

Props State
Comes from The parent Inside the component
Can the component change it? No — read-only Yes, with its setter
Used for Configuring a component Things that change over time

Never modify props. props.name = 'Bob' breaks React's assumptions. If a value needs to change, it belongs in state somewhere, and the new value flows down as a prop.

Common mistakes

  • Forgetting the curly braces: count="5" passes the string "5"; count={5} passes the number.
  • Calling a function instead of passing it: onClick={handleClick()} runs immediately on every render. Use onClick={handleClick} or onClick={() => handleClick(id)}. This is a classic cause of too many re-renders.
  • Passing an object as text: rendering {user} instead of {user.name} causes "Objects are not valid as a React child".
  • Prop drilling: passing the same prop through five layers of components. When that happens, consider React Context.

Props with TypeScript

TypeScript lets you declare what props a component expects, and catches mistakes before you run the code:

type GreetingProps = { name: string; excited?: boolean }

function Greeting({ name, excited = false }: GreetingProps) { ... }

(What is TypeScript?)


EasySpawn runs your React app — and the API and database behind it — on one server, with Claude Code on hand to explain any component you didn't write yourself. See how it works or join the waitlist.

Related: What Is React? · React useState Explained · What Is JSX? · React State Management

Keep reading