Components, JSX and Props
React is a JavaScript library for building interfaces out of components: functions that receive data and describe what should be displayed. When the data changes, React updates the DOM for you.
Starting a project
Create React App is deprecated. To learn, use Vite; for a full application, a framework such as Next.js or React Router.
npm create vite@latest ma-boutique -- --template react
cd ma-boutique && npm install && npm run dev
The current template installs React 19.3 and Vite 8; npm run lint runs oxlint, a linter that enforces, among other things, the rules of hooks.
A first component
function Bienvenue() {
return <h1>Welcome to the shop</h1>;
}
export default function App() {
return (
<main>
<Bienvenue />
<Bienvenue />
</main>
);
}
A component is a function whose name starts with a capital letter (otherwise React takes it for an HTML tag). You use it like a tag: <Bienvenue />.
The rules of JSX
JSX looks like HTML but it is compiled into JavaScript (<h1> becomes a call to a React function). Hence a few rules:
function Fiche() {
const nom = "City bike";
const prix = 499;
return (
<> {/* fragment: a single parent, without a needless div */}
<h2 className="titre">{nom}</h2> {/* className, not class */}
<p>{prix * 1.2} € incl. VAT</p> {/* any expression between braces */}
<label htmlFor="qte">Quantity</label>
<input id="qte" type="number" defaultValue={1} /> {/* tags are always closed */}
<p style={{ color: "green" }}>In stock</p> {/* style: an object */}
</>
);
}
Between braces you put an expression (variable, calculation, function call, ternary), not an if or for statement.
Props
Props are a component’s parameters. You receive them in an object, usually destructured:
function CarteProduit({ nom, prix, enStock = true }) { // default value
return (
<article>
<h2>{nom}</h2>
<p>{prix} €</p>
{!enStock && <p>Out of stock</p>}
</article>
);
}
<CarteProduit nom="Casque" prix={39} enStock={false} />
Strings are passed in quotes, every other value between braces: prix={39}, enStock={false}, options={{ couleur: "rouge" }}.
Props are read-only: a component must never modify them.
children
What is placed between the opening and closing tags arrives in the children prop:
function Carte({ titre, children }) {
return (
<section className="carte">
<h2>{titre}</h2>
{children}
</section>
);
}
<Carte titre="Delivery">
<p>Free on orders over €50.</p>
</Carte>
This is the basis of composition: small generic components assembled into complete interfaces.
Pure components
A component must behave like a pure function: with the same props, it returns the same JSX, without modifying any outside variable or calling any API during rendering. Side effects belong in event handlers or effects (lesson 4). In development mode, <StrictMode> deliberately calls your components twice to reveal impurities.
Key takeaways
- Component = a Capitalized function that returns JSX.
{expression},className, closed tags, a single parent.- Read-only props,
childrenfor composing.
Exercises
Solutions and tests stay on the server. In the student space, your code is run and checked, and the tutor gives hints before the solution.
Product card
Write the component
CarteProduit({ nom, prix, enStock = true })which displays:- an
<article>containing an<h2>with the name; - a paragraph with the price formatted by
formaterPrix(prix)(provided); - a paragraph
Rupture de stockonly ifenStockis false; - a button
Ajouter au panier, disabled (disabled) when out of stock.
const formaterPrix = (p) => new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR" }).format(p); export function CarteProduit({ nom, prix, enStock = true }) { // TODO }- an
Format a price (executed)
A pure function used by your components. Write
formaterPrix(prix)which returns the price in French format in euros withIntl.NumberFormat(12.5→"12,50 €").Note:
Intlinserts a non-breaking space before€; the tests normalize whitespace.function formaterPrix(prix) { // TODO }JSX rules
Which of these snippets is valid JSX?
- <div class="carte"><img src={url}></div>
- <><label htmlFor="q">Search</label><input id="q" /></>
- <p>{if (ok) { "Oui" }}</p>
- <h1>Title</h1><p>Text</p> (returned side by side with no parent)
End-of-lesson quiz
Why must a component’s name start with a capital letter?
- Only as an aesthetic convention
- So that React can tell it apart from a native HTML tag
- So that it is exported automatically
What does the children prop contain?
- The child components declared in the file
- The content placed between the component's opening and closing tags
- The list of props
Can a component modify its props?
- Yes, it's the normal way to update the display
- No, props are read-only
- Yes, but only children
The rest of the course
- State with useState and Events18 min
- Lists, Conditional Rendering and Shared State18 min
- Effects, Synchronization and Data Loading20 min
- useReducer, Context and Custom Hooks20 min
- Forms and Actions with React 1920 min