Composing components
The power of components is nesting them. You build small pieces, then assemble bigger pieces out of them, exactly like functions calling functions in Advanced JavaScript:
function Header() { return <header><h1>Task Tracker</h1></header>; } function TaskItem() { return <li>Water the plants</li>; } function App() { return ( <div> <Header /> <ul> <TaskItem /> <TaskItem /> </ul> </div> ); }
When React renders <App />, it calls App, sees <Header /> and <TaskItem /> inside, and calls those too, all the way down until only real tags remain. The result is a component tree.
Small components, assembled
Good React code reads like an outline. App tells you the page has a header and a list, and each child component handles its own details. Compare that with one giant function containing every tag on the page.
The same idea works in plain JavaScript with our string-returning functions from lesson 1-2. Composition is just functions calling functions, JSX only makes it look like markup.
Composition in plain JavaScript
card(title, body) returns a section string built from its two parameters, and page composes a header with two cards. This is the same nesting as the JSX version, without the syntax.
function header(title) { return "<header>" + title + "</header>"; } function card(title, body) { return "<section><h2>" + title + "</h2><p>" + body + "</p></section>"; } function page() { return header("Dashboard") + card("Weather", "Sunny") + card("Inbox", "3 new"); } console.log(page());
Output
<header>Dashboard</header><section><h2>Weather</h2><p>Sunny</p></section><section><h2>Inbox</h2><p>3 new</p></section>
card is called twice with different arguments and produces different output both times, which is reuse in its plainest form. Writing the two sections out by hand would work and would leave two copies of the markup to keep in step.
page reads like an outline, naming a header and two cards, and it contains no h2 or p tags at all. That is the property good React code has, where a parent tells you the shape of the page and each child owns its own details.
Composition here is only functions calling functions, and JSX changes nothing about that. The JSX version writes <Card title="Weather" body="Sunny" /> instead of card("Weather", "Sunny"), and the next unit is about that argument-passing syntax.
Note that page takes no parameters, so it always produces the same page. Making the card list data-driven is what unit 5's map lesson does, and it is the difference between an outline you typed and one derived from data.
What happens at a nested component tag
When React encounters <TaskItem /> while rendering, it calls the TaskItem function and uses the returned JSX in that spot.
A capitalized tag means to call this function, so React invokes TaskItem, receives <li>Water the plants</li>, and slots it into the tree. Rendering walks the whole tree this way until only real DOM tags remain.
The App example has <TaskItem /> twice, so the function is called twice and produces two independent li elements. Nothing is shared between the two calls, which is why a component can appear a hundred times on a page without the copies interfering.
The recursion has a natural stopping point. Lowercase tags like div, ul, and li are not functions, so React creates DOM nodes for them and descends no further into your code, which is the same base case as the render function you wrote in lesson 2-2.
Worth noting that React controls when this happens. You never call TaskItem() yourself, and React may call it again later when data changes, which is why a component that mutated something outside itself would misbehave in ways that are hard to predict.