Command Palette

Search for a command to run...

Hectal
PHASE 2Beginner ~22 min· topic 3 of 7

Topic 2.3

Passing Props

In one line

Props are the inputs of a component: the parent writes them like attributes, React collects them into one object, and the child reads that object (usually by destructuring) to decide what to show. Any JavaScript value can be a prop: strings, numbers, booleans, objects, arrays, functions and JSX.

Think of it like this

Ordering at a juice stall. The juice maker (the component) always works the same way, but your order changes the result: "mango, large, no ice". Props are the order slip. The parent writes the order, the component reads it and makes exactly that. The juice maker doesn't change your slip; it only reads it.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Props
The inputs of a component, written like attributes by the parent: <Avatar name="Asha" />.
Props object
The single object React builds from those attributes and passes to your function: { name: "Asha" }.
Destructuring props
Pulling fields out of the props object in the parameter list: function Avatar({ name }).
Expression
Any piece of JavaScript that produces a value. In JSX it goes inside { }.
Callback prop
A function passed as a prop so the child can tell the parent something happened, like onBuy.
Boolean shorthand
Writing a prop with no value, <Toggle on />, which means on={true}.
Reserved prop
key (and ref before React 19): React uses them itself and doesn't hand them to your component.

Step by step

01A component that can't change

Greeting always says the same thing. To greet different people you would need a new component for each. Props fix that.

Greeting.jsxwhole filejsx
function Greeting() {
  return <h2>Hello, Asha!</h2>;
}

02The parent passes a prop

The parent adds an attribute. The value can be anything; a string goes in quotes.

App.jsxwhole filejsx
<Greeting name="Asha" />
<Greeting name="Ravi" />

03React builds the props object

For each tag, React collects the attributes into an object and calls your function with it. <Greeting name="Ravi" /> becomes Greeting({ name: "Ravi" }).

React builds the props objectdiagram
Rendering diagram…

04The child reads it

Destructure the field you need and use it in the JSX. Now one component greets anyone.

Greeting.jsxwhole filejsx
function Greeting({ name }) {
  return <h2>Hello, {name}!</h2>;
}

05Pass other types with braces

Numbers, booleans, objects, arrays, functions and JSX all go inside { }. Only plain strings may use quotes.

App.jsxwhole filejsx
<ProductCard
  name="Mango juice"              // string
  price={60}                      // number
  inStock                         // boolean true (shorthand)
  tags={["cold", "fresh"]}        // array
  seller={{ name: "Ravi" }}       // object
  onBuy={() => alert("Bought!")}  // function
  badge={<strong>New</strong>}    // JSX
/>

06New props, new render

When the parent renders again with different values, React calls the child again with the new props object, and the screen follows. The child never stores or changes its props itself.

Try it yourself

  1. 1

    Add a third greeting

    In the first example, add <Greeting name="Meera" age={10} />. Predict the new console line before running.

  2. 2

    Pass a new prop

    Give ProductCard a rating prop (a number from 1 to 5) and show that many stars with "★".repeat(rating). Pass rating={4} to the mango juice. What happens to the lassi card if you don't pass it? ("★".repeat(undefined) is an empty string, so no stars.)

  3. 3

    Forget the braces in the parameter

    In the first example, change function Badge({ label, color }) to function Badge(label, color). Predict what appears, then run it. (Nothing sensible: label is now the whole props object and React throws because objects can't be shown.)

Code & diagrams

The props object, read two ways New tab

Each `<Greeting />` gets its own props object. The string came from quotes, the number from braces.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Greeting got { name: 'Asha', age: 9 }
Greeting got { name: 'Ravi', age: 11 }
Every kind of value as a prop New tab

One component, seven kinds of props. `onBuy` is a function: the child calls it on click, and the parent (which owns the message) updates. `badge={null}` shows nothing.

Preview

Press Run to see the page.

Console

Nothing logged yet.
Quotes make strings, braces make numbers New tab

`points="5"` passed the text "5", so `+ 1` glued the strings together. `points={5}` passed a number. React never converts prop types for you.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

string points + 1 = 51
number points + 1 = 6

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Render an object prop directly

In "Every kind of value as a prop", change Sold by {seller.name} from {seller.city} to Sold by {seller}.

terminal
$ Console
── what you'll see ──
Uncaught Error: Objects are not valid as a React child (found: object with keys {name, city}). If you meant to render a collection of children, use an array instead.

Break #2

Pass `"false"` in quotes

Change the lassi's inStock={false} to inStock="false".

terminal
$ Preview
── what you'll see ──
The lassi card says "In stock" and its Buy button is enabled.

Break #3

Try to read `key` as a prop

Render <Greeting key="a" name="Asha" age={9} /> and log props.key inside Greeting.

terminal
$ Console
── what you'll see ──
Greeting: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)

Myth vs fact

Myth

Props can only be strings, like HTML attributes.

Fact

Props can be any JavaScript value: numbers, booleans, objects, arrays, functions, JSX, even other components.

Myth

A child can change a prop to update the parent.

Fact

Props are read-only. To change the parent's data, the child calls a function the parent passed in (onBuy), and the parent updates its own state.

Myth

<Toggle on="false" /> turns it off.

Fact

That passes the truthy string "false". Use on={false} or leave the prop out.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    <Card a={1} /> compiles to jsx(Card, { a: 1 }). React creates a new props object on every render of the parent, even when every value is the same. That's why memo compares props field by field (shallowly) instead of by object identity (Topic 16.3).

  • ▸

    Inline objects, arrays and arrow functions (seller={{...}}, onBuy={() => ...}) are new values on every render. That's harmless by default, but it defeats memo on the child and can re-run effects that depend on them; useMemo/useCallback or the React Compiler fix it when it matters (Phase 16).

  • ▸

    In development, React freezes the props object (Object.freeze). Assigning to a prop in module code (which is always strict mode) throws TypeError: Cannot assign to read only property, so mutations are caught early (Topic 2.6).

  • ▸

    In React 19, ref is an ordinary prop for function components and forwardRef is no longer needed for new code. key remains special and is never visible to the component.

Remember this

  1. 1

    Props (short for *properties*) are how a parent passes data to a child. You write them like HTML attributes: <Avatar name="Asha" size={64} />. React gathers every attribute into one plain object, { name: "Asha", size: 64 }, and passes it as the first argument of your function. That object is called the props object.

  2. 2

    You can read it as function Avatar(props) { return <p>{props.name}</p>; }, but most code destructures it right in the parameter list: function Avatar({ name, size }). It's the same object; destructuring just pulls out the fields you need and shows, at a glance, which props the component expects. Forgetting the braces (function Avatar(name)) is a common slip: name is then the whole props object.

  3. 3

    Strings can be written in quotes: title="Hello". Every other type needs curly braces, which mean "this is a JavaScript expression": numbers size={64}, booleans featured={true}, null, variables name={user.name}, calculations price={qty * 10}. Writing size="64" passes the string "64", and "64" + 1 is "641", a silent bug. A prop written with no value, <Toggle on />, is shorthand for on={true}. Leaving a prop out entirely gives undefined.

  4. 4

    Objects and arrays pass with braces too: user={{ name: "Asha", city: "Pune" }} (outer braces mean "expression", inner braces are the object) and tags={["new", "sale"]}. You can't put an object directly on the screen ({user} throws "Objects are not valid as a React child"); show its fields instead: {user.name}. Arrays of strings or numbers render as text side by side; arrays of objects are turned into elements with map (Topic 3.2).

  5. 5

    Functions are props too: onBuy={handleBuy}. The parent decides *what happens*; the child decides *when to call it* (for example on a click). This is how a child talks back to its parent while data still flows down only (one-way data flow, Topic 0.2). By convention these props are named onSomething; Topic 4.1 covers event handlers in depth. JSX is just a value, so it can be a prop as well: icon={<StarIcon />} lets the parent decide what to show inside a slot of the child (Topic 2.5 builds on this).

  6. 6

    Two attribute names are reserved and never reach your component: key (used by React to tell list items apart, Topic 3.3) and, before React 19, ref. In React 19 ref is passed to function components as a normal prop (Topic 8.3). Props are read-only inside the child: you read them, you never assign to them (Topic 2.6). When the parent renders again with new values, the child receives a new props object and renders again with it.

Explain it without notes

01

What are props, and how does a component receive them?

02

When do you use quotes and when braces for a prop's value?

03

How does a child component tell its parent that something happened?

04

Why do some developers say "props flow down, events flow up"?

Practice

01

Write a Weather component that receives city (string), temp (number) and sunny (boolean) and shows Pune: 31°C ☀️ or Pune: 24°C ☁️. Render it for two cities.

02

Write a Tags component that receives an array items and shows them joined with · . Render it with three tags.

Trade-offs

  • ↔

    Many small props (name, city) make a component's needs explicit and easy to change; one object prop (user) is shorter to pass but hides which fields are used and changes identity whenever the parent rebuilds it.

  • ↔

    Passing JSX as a prop gives the parent full control of a slot, but too many slot props make a component hard to understand. Topic 2.5 shows when children is the cleaner choice.

Done when you can

  • I can pass props from a parent and read them in a child.

  • I can destructure props in the parameter list.

  • I know when to use quotes and when braces.

  • I can pass objects, arrays, functions and JSX as props.

  • I can let a child report an event through a callback prop.

  • I know that key is not a prop and that props are read-only.