Skip to content

Expert · React concepts · topic 57 of 64 · 35 min

Props and composition

Explanation

Props are the inputs of a component, passed like attributes: <DishCard name="Masala dosa" price={90} />. Data flows one way, from parent to child, and a component must never change its own props. The special children prop lets you wrap any content, and plain JavaScript (&&, the ternary) decides what to show.

What are props?

Props (short for properties) are the inputs you give a component. You write them like HTML attributes. React collects them into one object and passes that object to your function as its first argument.

javascript
function DishCard(props) {
  return (
    <div className="dish">
      <h3>{props.name}</h3>
      <p>Rs {props.price}</p>
    </div>
  );
}

// Using it:
<DishCard name="Masala dosa" price={90} />
<DishCard name="Veg biryani" price={160} />
Text props go in quotes; numbers, arrays, objects and functions go in { } (React code, runs in a React project)
Think of it like this: Think of a wedding card printing shop. The card design is the component. Each family brings an order slip with names, date and venue: those are the props. The same design prints a different card for every slip, and the printer never changes what is written on your slip.

Destructuring and default values

javascript
function DishCard({ name, price, veg = true, spicy = false }) {
  return (
    <div className="dish">
      <h3>{name} {veg ? '(veg)' : '(non-veg)'}</h3>
      <p>Rs {price}{spicy && ' - spicy'}</p>
    </div>
  );
}
Destructure props in the parameters; veg = true is a default used when the parent leaves veg out (React code, runs in a React project)
typescript
type DishCardProps = {
  name: string;
  price: number;
  veg?: boolean;
};

function DishCard({ name, price, veg = true }: DishCardProps) {
  return <h3>{name}: Rs {price} {veg && '(veg)'}</h3>;
}
In a TypeScript project (.tsx files), give props a type so mistakes show up in your editor (React code, runs in a React project)

Props are read-only

Careful: A component must never change its props: treat them like a function argument you only read. Never write props.price = 100 or push into an array prop. React expects components to be pure: the same props give the same output. If the screen must change, the parent passes new props (usually from its state, the next topic).

One-way data flow

Data flows down the tree: parent to child, through props. A child cannot reach up and change its parent's data. When a child needs to ask for a change, the parent passes a function as a prop, and the child calls it.

javascript
function AddButton({ onAdd }) {
  return <button onClick={onAdd}>Add</button>;
}

function DishRow({ dish }) {
  function handleAdd() {
    console.log('Add', dish.name);
  }
  return (
    <li>
      {dish.name} <AddButton onAdd={handleAdd} />
    </li>
  );
}
The parent gives the child a function; the child calls it when clicked (React code, runs in a React project)

children: wrapping content

Whatever you put between the opening and closing tags of a component arrives in a prop called children. This lets you build wrappers such as Card, Modal or PageLayout, which add a frame around any content. Building bigger parts from smaller ones like this is called composition.

javascript
function Card({ title, children }) {
  return (
    <section className="card">
      <h2>{title}</h2>
      {children}
    </section>
  );
}

<Card title="Delivery address">
  <p>12, MG Road, Bengaluru 560001</p>
  <button>Change</button>
</Card>
The p and button inside <Card> become its children (React code, runs in a React project)

Conditional rendering

To show something only sometimes, use plain JavaScript. Use a ternary (a ? b : c) to choose one of two things, && to show something or nothing, and an early return null to show nothing at all.

javascript
function StockBadge({ stock }) {
  if (stock === undefined) return null;
  return (
    <>
      {stock === 0 ? <span className="out">Out of stock</span> : <span>In stock</span>}
      {stock > 0 && stock < 5 && <span className="low">Only {stock} left</span>}
    </>
  );
}
null, false and undefined render nothing (React code, runs in a React project)
Careful: Be careful with && and numbers. {count && <Badge />} shows a 0 on the screen when count is 0, because 0 is a value React renders. Write {count > 0 && <Badge />} instead.
Tip: Passing the same prop down through many levels is called prop drilling. For data that many components need, such as the theme or the logged-in user, React has Context (createContext and useContext). Learn props well first; reach for Context only when drilling becomes painful.

Watch the lesson

Props and composition · 1/7

props = inputs of a component

Components become useful when you can give them data. That data is called props.

Prefer a video by a teacher? Find free videos on “react props and children tutorial conditional rendering” on YouTube ↗

In real life: Train search results

A railway booking site shows one TrainCard for every train in the search result. Each card gets props: name, number, departure time, fare and seatsLeft. The card shows "Available" in green, or "Waitlist" when seatsLeft is 0, using a ternary. A Card wrapper with children gives every box the same border and heading, and a "Book" button calls the onBook function the page passed down.

Practice (0/3 done)

Task 1 · Code · Javascript

A DishCard component destructures its props with defaults. Practise the same thing in plain JavaScript. Write dishLabel(props) that destructures name, price, veg (default true) and spicy (default false), and returns "<name> - Rs <price> (<type>)" where type is "veg" or "non-veg", with ", spicy" added inside the brackets when spicy is true. Do not change the props object. Examples: dishLabel({ name: "Masala dosa", price: 90 }) returns "Masala dosa - Rs 90 (veg)". dishLabel({ name: "Chicken 65", price: 220, veg: false, spicy: true }) returns "Chicken 65 - Rs 220 (non-veg, spicy)".

Task 2 · Code · Javascript

A StockBadge component decides what to show from its stock prop. Write the decision as a plain function stockMessage(stock). Return null when stock is undefined or null (render nothing), "Out of stock" when stock is 0, "Only N left" when stock is 1 to 4 (for example "Only 3 left"), and "In stock" when stock is 5 or more.

Task 3 · Practice

In your Vite project, build a small menu page. Make a Card component that shows a title and its children. Make a DishCard component with the props name, price, veg (default true) and stock, and an AddButton that receives an onAdd function prop. Show "Out of stock" or "Only N left" with conditional rendering. Use Card to wrap two sections: "Breakfast" and "Lunch".

Quick quiz

Question 1

1.How do you pass the number 90 as the price prop?

Question 2

2.A child component needs to change data that its parent owns. What is the React way?

Question 3

3.What is the children prop?

Question 4

4.count is 0. What does {count && <Badge count={count} />} show on screen?

Question 5

5.Inside a component, can you write props.name = 'New name'?

Read more (free)

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

← Previous: Why React: components and JSX