AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Blog
  3. 01 — Components and JSX — The Building Blocks React Asks For

01 — Components and JSX — The Building Blocks React Asks For

August 13, 20268 min read
Download as Markdown

"Just components" was how I hand-waved React's core unit, and the vagueness leaked into everything else. The idea that pinned it down: a component is a function that returns JSX, and the entire app is a tree of these functions talking to each other through props. [1] Once I stopped thinking "React magic" and started thinking "function calls that return descriptions of UI," most of the API made sense on its own.

JSX: HTML you can write inside JavaScript

JSX looks like HTML inside JavaScript, and that resemblance is the whole point — it lets me describe what a piece of UI looks like using familiar markup, right next to the logic that produces it [1][2]. Two things keep it from being literal HTML:

  • It compiles down to React.createElement(...) calls — it's syntactic sugar, a shorthand for something I could write out the long way, not a string template.
  • The DOM attributes are camelCased (className, not class; htmlFor, not for), because JSX is closer to JavaScript than to HTML.

Curly braces {} are the escape hatch: anything inside them is evaluated as a JavaScript expression. {user.name}, {items.length}, {cond ? 'on' : 'off'} all drop straight into the markup. The way of thinking is "JSX is a value," not "JSX is a template" — and because it's a value, I can put it in a variable, return it from a function, pass it around.

function Greeting({ name }) {
// the function returns a JSX expression — that's the whole component
return <h1 className="title">Hello, {name}</h1>;
}

The function is the component

A functional component is literally a JavaScript function that accepts props as its argument and returns JSX [1][3]. No class, no lifecycle ceremony — just input in, description out. That single contract is why I now default to functional components everywhere; the class form exists for legacy, and the official guidance points at functions.

From that one contract, three corollaries I had to internalize:

  • Components compose by nesting. Putting <Greeting /> inside <App /> is how the tree is built — a component's JSX can reference other components, recursively [1].
  • Props are read-only inputs. Whatever the parent passes in, the child reads; the child never mutates props [1][5].
  • Same props in, same JSX out. A component is a pure function of its props and state. That purity is what makes the tree predictable.

Lists, keys, and why React needs a stable identity

Rendering a list is just array.map(item => <Row ... />). The gotcha is the key prop — React needs a stable, unique identifier on each repeated element to track which item is which across renders [4]. Without a key, React falls back to array index, and that goes wrong the moment list order changes (reorders, inserts, deletes produce subtle state-leak bugs).

{items.map(item => (
<li key={item.id}>{item.label}</li>
))}

The rule I follow: key comes from the data's identity, never from array position, unless the list is truly static and never reordered. Using the index as key is the single most common footgun in list rendering, and it's invisible until something reorders.

Conditional rendering is just JavaScript

There's no v-if or *ngIf directive. Conditional rendering is plain JavaScript operators producing JSX or not [6]:

  • && for "render this or nothing": {isLoading && <Spinner />}
  • ternary ? : for "render A or B": {user ? <Dashboard /> : <Login />}
  • early return null inside the component body for "render nothing"

This is the payoff of "JSX is a value" — the same expressions I'd write in any JavaScript function control what renders. No special syntax to learn.

Events: functions passed, not strings

Handling events mirrors the DOM, with two JSX-isms: event names are camelCased (onClick, not onclick), and I pass an actual function as the handler rather than a string of code [7]. The handler receives a React Synthetic Event — a thin wrapper around the native event that normalizes behavior across browsers.

function Button() {
const handleClick = (e) => {
e.preventDefault();
// ...
};
return <button onClick={handleClick}>Save</button>;
}

Composition over inheritance, and the patterns that came with it

React's official line is unambiguous: use composition, not inheritance, to share code between components [8]. The most useful composition primitive is the children prop — a parent receives whatever JSX sits between its tags, and can wrap it, position it, or pass it through. That's how layout shells, cards, and modals are built.

Two older code-sharing patterns ride on top of composition, and the roadmap lists both, but both are mostly retired in modern code:

  • Render props. A component accepts a function as a prop and calls it to decide what to render, inverting control — handing the "what to render" decision back to the caller [9]. It's a clean pattern, but hooks largely replaced it for logic reuse.
  • Higher-Order Components (HOC). A function that takes a component and returns a new, wrapped component — withAuth(Component) [10]. HOCs stack awkwardly, obscure the data flow, and fight TypeScript. The roadmap itself notes they're uncommon now; hooks took the job.
App() returns JSX tree Header Sidebar List Row Row Row props flow down the tree each node is a function returning JSX; data flows down via props

The diagram is the way of thinking in one frame: an app is a tree of functions, each returning JSX, each receiving data from its parent through props. Composition is just calling those functions; inheritance never enters the picture.

How I use this

When I scaffold any new screen, I sketch the tree first — what's the top component, what are its children, what props cross each edge — before writing a line of JSX. That habit forces the data flow to be obvious up front. The other rules I keep by default: functional components only, key from a stable id (never the index), conditional rendering with &&/ternary (never a special directive), and composition through children rather than HOCs. The rare time I reach for a render prop, it's for a genuinely inverted-control case like a virtualized list; for ordinary logic reuse, a custom hook is what I write instead.

References

[1] React team, "Quick Start," react.dev, 2024. [Online]. Available: https://react.dev/learn

[2] React team, "Writing markup with JSX," react.dev, 2024. [Online]. Available: https://react.dev/learn/writing-markup-with-jsx

[3] R. Wieruch, "The difference between components, elements, and instances," robinwieruch.de, 2023. [Online]. Available: https://www.robinwieruch.de/react-element-component/

[4] React team, "Rendering lists: keeping list items in order with key," react.dev, 2024. [Online]. Available: https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key

[5] React team, "Passing props to a component," react.dev, 2024. [Online]. Available: https://react.dev/learn/passing-props-to-a-component

[6] React team, "Conditional rendering," react.dev, 2024. [Online]. Available: https://react.dev/learn/conditional-rendering

[7] React team, "Responding to events," react.dev, 2024. [Online]. Available: https://react.dev/learn/responding-to-events

[8] React team, "Passing JSX as children," react.dev, 2024. [Online]. Available: https://react.dev/learn/passing-props-to-a-component#passing-jsx-as-children

[9] patterns.dev, "Render Props Pattern," 2023. [Online]. Available: https://www.patterns.dev/posts/render-props-pattern/

[10] React team, "Higher-Order Components," legacy docs. [Online]. Available: https://reactjs.org/docs/higher-order-components.html

Knowledge check · Question 1 of 5

What is a React functional component, at its simplest?

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!