Components & JSX
Function components, JSX, props, composition.
React has one big idea: your UI is a function of state. You write functions that return descriptions of what the screen should look like, and React figures out the DOM updates. The unit of that function is a component, and the syntax it returns is JSX. Once you really get those two things, the rest is footnotes.
A component is just a function
Forget classes, forget lifecycle methods, forget anything you might have read from 2017. A modern React component is a JavaScript function whose name starts with a capital letter and which returns JSX.
function Greeting() {
return <h1>Hello, world!</h1>;
}That's it. Greeting is a component. You can render it anywhere by writing <Greeting />. The capital letter is how React tells your components apart from built-in HTML tags like div or span.
<header> renders an HTML header element. <Header> renders your Header component. Get this wrong and React quietly creates an unknown DOM tag instead of complaining.JSX is sugar for createElement
JSX looks like HTML but it's really JavaScript. Every tag compiles down to a function call. These two snippets are identical:
// What you write
const tree = <h1 className="title">Hello</h1>;
// What the compiler produces (roughly)
const tree = React.createElement("h1", { className: "title" }, "Hello");That object createElementreturns is just data. A plain JavaScript object describing "an h1 with these props and these children." React calls these objects elements. They are not DOM nodes. They are a recipe React reads later to build or update the actual DOM.
Because JSX is JavaScript, you can use it like any other expression. Store it in a variable, return it from a function, pass it as an argument, put it in an array. The curly braces { } switch from "JSX mode" back to "JavaScript mode," so anything that evaluates to a value goes there.
const name = "Ada";
const tree = <h1>Hello, {name.toUpperCase()}!</h1>;className instead of class, and htmlFor instead of for. Style is an object, not a string: style={{ color: "red" }}.Props are the function arguments
A component takes one argument, an object called props. Whatever attributes you put on the JSX tag become keys on that object. Destructure them at the top of the function for readability.
function Avatar({ name, size = 40 }) {
return <img src={`/avatars/${name}.png`} width={size} height={size} alt={name} />;
}
// Used like this:
<Avatar name="ada" size={64} />Props flow down. A parent passes data to its children as props. Children cannot reach up and change them. This one-way flow is what makes React apps predictable.
The children prop is special
Anything you nest between a component's opening and closing tags comes in as a special prop called children. This is what makes layout components possible.
function Card({ children, title }) {
return (
<div className="card">
<h3>{title}</h3>
<div className="card-body">{children}</div>
</div>
);
}
// Usage:
<Card title="Hello">
<p>Any JSX you put in here lands in {children}.</p>
</Card>This is React's answer to the "how do I make a reusable wrapper" question. No slots, no transclusion, just children.
Composition over configuration
React really wants you to build big components by sticking small components together. Instead of one Dialog with 47 boolean props for every possible variant, you make a Dialog that takes children and you compose it with Header,Body, and Footer children.
Try it: a Card component
Play with the props. Add a third Card with your own content. Try removing title. Notice how JSX is just data you can move around.
createElement calls. <Card title="hi">X</Card> is createElement(Card, { title: "hi" }, "X"). Suddenly all the weird quirks (why {children}, why curly braces, why uppercase) make sense.Quiz
What does <Header /> render vs <header />?
Recap
- A component is a function that returns JSX, with a capitalized name.
- JSX is JavaScript. Tags compile to
createElementcalls and produce plain objects called elements. - Props are the function argument. They flow one way, from parent down to child.
childrenis the prop that holds whatever is nested between your component's tags.- Build complex UIs by composing small components, not by adding props.