React · Getting Started

Props

Props are a component’s inputs — like arguments to a function. They let one component be reused with different data, and let parents tell children what to show and what to do.

Beginner 5 min Lesson 7 of 42Examples target React 19 with Vite.
Before you start:Components
0/42 in React
On this page · 5 min · Beginner

Learning objectives#

  • Pass and read props
  • Destructure props with default values
  • Pass functions as props (callbacks)
  • Use the special children prop

Explanation#

Props are passed as attributes: <ProductCard name="Pen" price={20} />. Strings can use quotes; everything else goes in { }.

The component receives one object; destructure it: function ProductCard({ name, price = 0 }). Defaults apply when a prop is missing.

Props are read-only. A component must never change its props — data flows one way, from parent to child.

To let a child talk back, pass a function: <AddButton onAdd={handleAdd} />. The child calls onAdd(...) and the parent decides what happens.

children is whatever you put between the tags: <Card><p>Hi</p></Card>. It makes layout components (Card, Modal, Layout) easy.

Spread passes many props at once: <Input {...field} />. Use it carefully — explicit props are easier to read.

Syntax#

JSX Illustrative
<Button label="Save" disabled={false} onClick={save} />


function Button({ label, disabled = false, onClick }) {
  return <button disabled={disabled} onClick={onClick}>{label}</button>;
}

Code example: Data down, events up, children inside#

JSXShop.jsx Runnable
import { useState } from 'react';


function Card({ title, children }) {
  return (
    <section style={{ border: '1px solid #ddd', padding: 12, marginBottom: 8 }}>
      <h3>{title}</h3>
      {children}
    </section>
  );
}


function ProductRow({ name, price, currency = '₹', onAdd }) {
  return (
    <p>
      {name} — {currency}{price}{' '}
      <button onClick={() => onAdd(name)}>Add</button>
    </p>
  );
}


export default function Shop() {
  const [cart, setCart] = useState([]);


  function handleAdd(name) {
    setCart(prev => [...prev, name]);
  }


  return (
    <>
      <Card title="Products">
        <ProductRow name="Pen" price={20} onAdd={handleAdd} />
        <ProductRow name="Notebook" price={60} onAdd={handleAdd} />
      </Card>
      <Card title={`Cart (${cart.length})`}>
        <p>{cart.length ? cart.join(', ') : 'Empty'}</p>
      </Card>
    </>
  );
}
Expected output
Two cards: “Products” with Pen and Notebook rows, and “Cart (0)” showing “Empty”. Clicking Add on a row adds that product to the cart; the second card title and list update, e.g. “Cart (2)” — “Pen, Notebook”.

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. Card receives title as a prop and renders whatever is nested inside it via children.
  2. ProductRow receives data (name, price) and a default currency.
  3. onAdd is a function prop: the row calls it, Shop decides what adding means.
  4. Shop owns the cart state; the rows never change it directly.

Real-world use case#

A design system exposes <Button variant="primary" size="sm" onClick={...}> and <Modal title="..." onClose={...}>{content}</Modal>. Every team uses the same components with different props.

Common mistakes#

Changing props

props.price = 10 breaks one-way data flow and React’s assumptions. Copy into state or ask the parent via a callback.

Calling the function instead of passing it

onAdd={handleAdd("Pen")} runs on every render. Pass a function: onAdd={() => handleAdd("Pen")}.

Prop drilling through many levels

Passing the same prop through five components that do not use it is a sign to use context or composition.

Best practices#

  • Destructure props with defaults
  • Name callback props onSomething
  • Use children for layout components
  • Keep props few and meaningful

Remember this#

Props in, JSX out. Props are read-only.

Data down via props; events up via callback props.

children = what goes between the tags.

Practice exercise#

Your task: Create an Alert component with a type prop ("success" or "error", default "success") and children. Success shows a green border, error a red one.

Need a hint?
style={{ border: `2px solid ${type === "error" ? "red" : "green"}` }}.
Show solution
JSX Runnable
export default function Alert({ type = 'success', children = 'Saved!' }) {
  const colour = type === 'error' ? 'red' : 'green';
  return (
    <div role="alert" style={{ border: `2px solid ${colour}`, padding: 8 }}>
      {children}
    </div>
  );
}
// <Alert type="error">Payment failed</Alert>

Mini quiz#

Props quizMultiple choice Question 1 of 3

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

Score so far: 0/0

Want more? Practise all React MCQs · React interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.