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. UseonClick={handleClick}oronClick={() => 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) { ... }
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
"ReferenceError: window is not defined" in Next.js: How to Fix It
window, document and localStorage only exist in the browser. Next.js renders components on the server first, where they don't exist. Why it happens, and the fixes: useEffect, 'use client', typeof checks, dynamic imports with ssr: false, and libraries that touch window on import.
What Is TypeScript? JavaScript With Labels, Explained for Beginners
TypeScript is JavaScript plus types: labels that say what kind of value each thing holds, checked before your code runs. What it looks like, why AI tools default to it, what .ts and .tsx files are, and how to read the red squiggles.