React Props

React Props

Props (short for properties) are how you pass data from a parent component to a child component. Props flow in one direction: parent โ†’ child. They are read-only โ€” a component must never modify its own props.

Passing Props

// Parent sends props like HTML attributes
function App() {
  return (
    <Product
      name="React Handbook"
      price={29.99}
      inStock={true}
      tags={["books", "programming"]}
      onAddToCart={() => console.log("Added!")}
    />
  );
}

// Child receives props as a single object โ€” destructure for clarity
function Product({ name, price, inStock, tags, onAddToCart }) {
  return (
    <div className="product">
      <h2>{name}</h2>
      <p className="price">${price.toFixed(2)}</p>
      <p>{inStock ? "โœ… In Stock" : "โŒ Out of Stock"}</p>
      <ul>{tags.map(t => <li key={t}>{t}</li>)}</ul>
      <button onClick={onAddToCart} disabled={!inStock}>
        Add to Cart
      </button>
    </div>
  );
}

Default Props

function Button({ label, variant = "primary", size = "md", disabled = false, onClick }) {
  return (
    <button
      className={`btn btn-${variant} btn-${size}`}
      disabled={disabled}
      onClick={onClick}
    >
      {label}
    </button>
  );
}

// Without variant or size, defaults kick in
<Button label="Save" onClick={handleSave} />
// Renders with variant="primary" and size="md"

Prop Types (Runtime Validation)

import PropTypes from "prop-types"; // npm install prop-types

function UserCard({ name, age, email, onContact }) {
  return (/* ... */);
}

UserCard.propTypes = {
  name:      PropTypes.string.isRequired,
  age:       PropTypes.number,
  email:     PropTypes.string.isRequired,
  onContact: PropTypes.func,
};

UserCard.defaultProps = {
  age: null,
  onContact: () => {},
};

Spreading Props

// Pass all props of an object at once using spread
function TextInput(props) {
  return <input className="text-input" {...props} />;
}

// Usage: all HTML input attributes work automatically
<TextInput
  type="email"
  placeholder="Enter email"
  required
  autoFocus
/>

๐Ÿง  Test Yourself

Can a child component modify its own props?