Components, props and JSX
Pure components, JSX rules, keys in lists and composition with children.
Updated
What React is
React is a library for building interfaces out of components. The core idea: UI = f(state) — you describe what the interface looks like for some data, and when the data changes, React updates the DOM on its own.
| Imperative (the DOM directly) | Declarative (React) |
|---|---|
"find the list, create an li, set the text, append it" |
"for this array, the list looks like this" |
| you keep track of what's on screen | React compares and applies only the differences |
What a component is
A component is a function that returns UI (JSX). You write it once and use it like your own HTML tag, as many times as you want.
type Props = { name: string; role?: 'admin' | 'user' }
export function UserBadge({ name, role = 'user' }: Props) {
return <span className="badge">{name} · {role}</span>
}
<UserBadge name="Ana" role="admin" />
<UserBadge name="John" />- The name starts with a capital letter — otherwise React treats it as an HTML tag.
- It receives props — data from the parent, like arguments.
- Props are read-only: you never change them inside the component.
- It must be pure: the same props → the same JSX, with no side effects during rendering.
What JSX is
JSX is syntax that looks like HTML but is JavaScript: <Card title="x" /> becomes a function call. Differences from HTML:
| HTML | JSX | Why |
|---|---|---|
class |
className |
class is a reserved word in JS |
for |
htmlFor |
the same |
onclick="..." |
onClick={fn} |
camelCase, you pass the function |
style="color: red" |
style={{ color: 'red' }} |
a JS object |
<br> |
<br /> |
every tag is closed |
| several elements at the root | a single root or <>...</> (a fragment) |
a function returns one value |
Inside {} you put any JS expression: variables, calls, ternaries, map.
Conditional rendering — the options
| Option | When |
|---|---|
{isAdmin && <Panel />} |
show it or not |
{loading ? <Spinner /> : <List />} |
one of two |
if (!user) return <Login /> before the main return |
big branches, early return |
an object map: {icons[status]} |
many variants |
The trap: {count && <List />} with count = 0 renders 0. Use count > 0 &&.
Lists and keys
<ul>
{products.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>key tells React which element is which between renders. It must be unique among siblings and stable:
| Key | Result |
|---|---|
item.id from the data |
✓ correct |
the index (i) |
✗ on delete / reorder, state (inputs, focus) stays at the wrong position |
Math.random() |
✗ every render = a new element, everything is lost |
A trick: change a component's key → React resets it completely.
Composition with children
children = whatever you put between the component's tags. That's how you build flexible components without dozens of props:
function Card({ title, children }: { title: string; children: React.ReactNode }) {
return (
<section className="card">
<h2>{title}</h2>
{children}
</section>
)
}
<Card title="Profile">
<UserBadge name="Ana" />
<button>Edit</button>
</Card>| Approach | Example | Problem |
|---|---|---|
| configuration props | <Card showHeader showFooter footerText="..." /> |
grows forever |
| composition | <Card><Card.Header />...</Card> |
flexible |
Summary
- A component = a pure function that takes props and returns JSX.
- JSX = JS with HTML-like syntax:
className,onClick={fn},{expressions}. - A stable
keyfrom the data in lists; composition withchildren.