Props

React · Lesson 5 of 29 6 min read Updated

A component that always shows the same thing is not very useful. Props (short for properties) let a parent component pass data to a child, so one ProductCard can show a cricket bat, a football or a racket depending on what you give it.

In this lesson you will pass and read props, set default values, use the special children prop to wrap content, and learn why a component must never change its own props.

Passing and reading props

You pass props the same way you write HTML attributes. Fixed text goes in quotes; every other value goes in curly braces. React collects all of them into one object and passes it as the first argument of your component function.

React JSXTry it yourself
import { createRoot } from "react-dom/client";

function ProductCard({ name, price, inStock, rating }) {
  return (
    <article style={{ border: "1px solid #ddd", padding: 10, marginBottom: 8 }}>
      <h3>{name}</h3>
      <p>₹{price.toLocaleString("en-IN")}</p>
      <p>Rating: {rating} / 5</p>
      <p>{inStock ? "In stock" : "Out of stock"}</p>
    </article>
  );
}

function Shop() {
  return (
    <>
      <ProductCard name="English willow bat" price={4999} inStock={true} rating={4.6} />
      <ProductCard name="Leather ball" price={650} inStock={false} rating={4.1} />
      <ProductCard name="Batting gloves" price={1299} inStock rating={4.4} />
    </>
  );
}

createRoot(document.getElementById("root")).render(<Shop />);

function ProductCard({ name, price, inStock, rating }) uses destructuring to pull the four values out of the props object. Without destructuring you would write function ProductCard(props) and then props.name, props.price and so on. Both are correct; destructuring is shorter and shows at a glance which props the component expects.

Two details are worth noticing. price={4999} passes a number; price="4999" would pass a string. And inStock on its own, with no value, is shorthand for inStock={true}.

Props can be any value

Props are not limited to strings and numbers. You can pass arrays, objects, functions and even JSX:

React JSX
<OrderSummary
  items={["Idli", "Vada", "Filter coffee"]}
  customer={{ name: "Ananya", city: "Kochi" }}
  onCancel={() => console.log("cancelled")}
  icon={<span>☕</span>}
/>

Passing a function as a prop is how a child tells its parent that something happened, such as a click. You will use that pattern a lot from Handling Events onwards.

Default values

If a parent does not pass a prop, its value is undefined. Give a prop a default value with the normal JavaScript default syntax inside the destructuring:

React JSXTry it yourself
import { createRoot } from "react-dom/client";

function Avatar({ name, size = 48, photo = "https://course.ethicscomputer.in/assets/samples/avatar.svg" }) {
  return (
    <figure style={{ display: "inline-block", margin: 8, textAlign: "center" }}>
      <img src={photo} alt={name} width={size} height={size} style={{ borderRadius: "50%" }} />
      <figcaption>{name}</figcaption>
    </figure>
  );
}

function Team() {
  return (
    <>
      <Avatar name="Rohan" />
      <Avatar name="Meera" size={80} />
      <Avatar name="Farhan" size={32} />
    </>
  );
}

createRoot(document.getElementById("root")).render(<Team />);

The default is used only when the prop is missing or undefined. If a parent passes size={null} or size={0}, the default is not used.

The children prop

Whatever you put between a component's opening and closing tags arrives as a special prop called children. This lets you build wrapper components such as cards, panels and page layouts that do not need to know what is inside them.

React JSXTry it yourself
import { createRoot } from "react-dom/client";

function Card({ title, children, tone = "info" }) {
  const colours = { info: "#087ea4", warning: "#b45309" };
  return (
    <section style={{ border: `2px solid ${colours[tone]}`, borderRadius: 8, padding: 12, marginBottom: 10 }}>
      <h3 style={{ marginTop: 0, color: colours[tone] }}>{title}</h3>
      {children}
    </section>
  );
}

function App() {
  return (
    <>
      <Card title="Exam timetable">
        <p>Maths on Monday, Physics on Wednesday.</p>
      </Card>
      <Card title="Fee reminder" tone="warning">
        <p>Last date for the hostel fee is 10 November.</p>
        <button>Pay ₹18,500</button>
      </Card>
    </>
  );
}

createRoot(document.getElementById("root")).render(<App />);

The Card component draws the border and title; the parent decides the contents. This idea is called composition, and it is the main way to reuse layout in React.

Props are read-only

Props flow one way: from parent to child. A component must treat its props as read-only and never change them.

React JSX
function Price({ amount }) {
  amount = amount * 1.18; // avoid: reassigning a prop is confusing
  return <p>₹{amount}</p>;
}

function PriceWithGst({ amount }) {
  const withGst = amount * 1.18; // good: compute a new local value
  return <p>₹{withGst.toFixed(2)}</p>;
}

Changing a prop object, such as props.customer.city = "Pune", is worse: it changes the parent's data behind its back, breaking the purity rule from the previous lesson. When a value needs to change over time (because of a click or typing), it belongs in state, which you will learn in State with useState. The parent can then pass the new value down as a prop.

Spreading props

Sometimes a component forwards all of its props to a child. The spread syntax {...props} passes every property at once:

React JSX
function PrimaryButton(props) {
  return <button className="btn-primary" {...props} />;
}

// <PrimaryButton type="submit" disabled>Save</PrimaryButton>

This is handy for small wrapper components around HTML elements. Do not overuse it: spreading hides which props a component really uses.

Common mistakes

  • Passing numbers as strings. price="499" is the text "499", so price + 1 gives "4991". Use price={499}.
  • Forgetting the braces when destructuring. function Card(title) receives the whole props object in title. Write function Card({ title }).
  • Modifying props. Never assign to a prop or change a prop object. Compute new local values or use state.
  • Expecting children to be an array. It can be a single element, a string, an array or nothing. Render it with {children} and let React handle it.

Key points

  • Props pass data from a parent to a child, written like HTML attributes.
  • A component receives one props object; destructure it in the parameter list.
  • Props can be any JavaScript value: strings, numbers, arrays, objects, functions and JSX.
  • Set defaults with { size = 48 }; they apply only when a prop is undefined.
  • Content between a component's tags arrives as the children prop.
  • Props are read-only; values that change over time belong in state.

Exercise

Write a Student component with props name, course, year (default 1) and children. It should show the name in a heading, a line such as "BCA, year 2", and then the children. Render three students, one without a year prop, and give one of them a paragraph of children such as "Class representative".

Show solution
React JSX
import { createRoot } from "react-dom/client";

function Student({ name, course, year = 1, children }) {
  return (
    <div style={{ borderBottom: "1px solid #ccc", padding: 8 }}>
      <h3>{name}</h3>
      <p>{course}, year {year}</p>
      {children}
    </div>
  );
}

function ClassList() {
  return (
    <>
      <Student name="Priya Sharma" course="BCA" year={2}>
        <p>Class representative</p>
      </Student>
      <Student name="Aarav Gupta" course="BCA" />
      <Student name="Isha Khan" course="B.Com" year={3} />
    </>
  );
}

createRoot(document.getElementById("root")).render(<ClassList />);

Aarav has no year prop, so the default 1 is used. Priya's paragraph arrives as children and appears below her course line.

Quick Quiz

1. How does a component receive its props?

2. What is children in <Card><p>Hello</p></Card>?

3. When is a destructuring default such as size = 48 used?

4. A value must change when the user clicks a button. Where should it live?

Learn React with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call