Components and Props
Building components, passing data down, and why props are read-only.
What you'll learn
- Writing a component, and why the capital letter matters
- Passing props, with defaults and destructuring
- The
childrenprop, and composition through it - Why a component must never write to its own props
A component is a function
It takes an object of properties and returns JSX. That is all:
The capital letter is not a style preference. JSX treats a lowercase tag as
a built-in DOM element and a capitalised one as a component. <badge /> would
render an unknown HTML element rather than call your function.
Destructuring props
Nearly all React code unpacks props in the signature, using the destructuring from the refresher. It documents what a component accepts at a glance, and gives you a place for defaults:
Props are not limited to strings. Numbers, booleans, objects, arrays, and functions all pass the same way — anything that is a JavaScript value.
Props are read-only
A component must never modify the props it receives. React assumes that given the same props, a component renders the same thing; writing to props breaks that assumption and the result is a component whose output depends on how many times it happened to run.
function Total({ items }) {
items.push({ name: "tax" }); // never do this — it mutates the caller's array
return <p>{items.length} items</p>;
}
If a value needs to change over time, it belongs in state, which is the subject of Managing State with useState. The division is worth memorising now:
- Props come from the parent. The component reads them.
- State belongs to the component. The component changes it.
Data flows one way — down. A child cannot reach up and change its parent's data; the parent passes a function down instead, which is covered in Lifting State Up.
children
Everything between a component's opening and closing tags arrives as the
children prop. This is what makes components composable rather than
configurable:
Without children, Card would need a prop for every possible thing it might
contain. With it, Card does not need to know. That trade — composition over
configuration — comes back in Composition over Configuration.
Passing functions
A prop can be a function, which is how a child tells its parent that something happened:
ActionButton knows nothing about saving or deleting. It knows it has a label
and something to call — which is why it can be reused for both.
Common mistakes
- A lowercase component name.
<badge />is an HTML tag, not your function. - Mutating props. Treat them as read-only; use state for what changes.
- Forgetting
children. If a component wraps content, it needs it. - A prop per variation. Six booleans usually means you wanted
children.
Exercise
UserCard currently hard-codes everything. Give it name and role props with
a default role of "member", and let the caller pass extra content as
children. Both cards below should render without changing App.