Runnable lesson · press Try it on the examples to edit and run them here.
Real API data is messier than the examples in textbooks: fields are missing, names are awkward, dates are strings, lists are nested. This lesson shows how to turn a response into a safe, tidy screen.
Look at the data first
Before you write JSX, read a real response (use the Network tab of the browser’s developer tools, or the API docs). Note the shape: which fields are always there, which can be null or missing, and which are lists.
const response = {
id: 7,
title: "Mastering React",
price_cents: 2999,
published_at: "2026-03-15T09:30:00Z",
author: { first_name: "Jane", last_name: "Doe" },
cover_url: null,
reviews: [
{ id: 1, rating: 5, text: "Great book" },
{ id: 2, rating: 4, text: null },
],
};
function App() {
return (
<article>
<h2>{response.title}</h2>
<p>By {response.author.first_name} {response.author.last_name}</p>
<p>{response.reviews.length} reviews</p>
</article>
);
}
Shape the data once, near the edge
APIs use their own names and units (price_cents, first_name, ISO date strings). Convert the response into the shape your components want in one place (a small function), instead of scattering conversions through the JSX:
function toBook(api) {
return {
id: api.id,
title: api.title,
price: api.price_cents / 100,
published: new Date(api.published_at),
author: `${api.author.first_name} ${api.author.last_name}`,
coverUrl: api.cover_url, // may be null
reviews: api.reviews ?? [],
};
}
const apiResponse = {
id: 7,
title: "Mastering React",
price_cents: 2999,
published_at: "2026-03-15T09:30:00Z",
author: { first_name: "Jane", last_name: "Doe" },
cover_url: null,
reviews: [
{ id: 1, rating: 5, text: "Great book" },
{ id: 2, rating: 4, text: null },
],
};
const money = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
const dateFmt = new Intl.DateTimeFormat("en-GB", { dateStyle: "long", timeZone: "UTC" });
function Book({ book }) {
return (
<article>
<h2>{book.title}</h2>
<p>{book.author}</p>
<p>{money.format(book.price)} - published {dateFmt.format(book.published)}</p>
{book.coverUrl ? <img src={book.coverUrl} alt={`Cover of ${book.title}`} /> : <p>No cover image</p>}
<ul>
{book.reviews.map((r) => (
<li key={r.id}>{"★".repeat(r.rating)} {r.text ?? "(no comment)"}</li>
))}
</ul>
</article>
);
}
function App() {
return <Book book={toBook(apiResponse)} />;
}
toBook is a plain function you can test without React. If the API changes a field name, you edit one place.
Defend against missing data
- Optional chaining
user?.address?.cityreturnsundefinedinstead of crashing when something in the chain is missing. See Optional Chaining. - Nullish coalescing
value ?? "fallback"replaces onlynullorundefined(Nullish Coalescing). - Defaults for lists:
const items = data.items ?? []. - Check types at the boundary. A response is not guaranteed to match its documentation. For important data, validate it with a schema library or at least check the fields you rely on.
function App() {
const user = { name: "Ada" }; // no address at all
return <p>City: {user.address?.city ?? "unknown"}</p>;
}
The error you would see without the ?. is the famous “Cannot read properties of undefined”.
Dates, money and numbers
- APIs send dates as ISO strings (
"2026-03-15T09:30:00Z"); convert withnew Date(...)and format withIntl.DateTimeFormat(Date formatting). - Money is often in cents to avoid floating-point errors; convert for display with
Intl.NumberFormat. - IDs may be numbers or strings; keep them consistent when comparing.
Images from APIs
Always provide alt text, set width and height (or an aspect ratio) so the layout does not jump, and handle a missing URL with a placeholder. Use loading="lazy" for images far down the page.
Do not render untrusted HTML
If an API returns HTML (for example a rich-text description), React will show the tags as text. Avoid dangerouslySetInnerHTML. If you truly need it, sanitise the HTML with a library built for that, because API data can contain scripts. See API Security Fundamentals.
Keep keys stable
Use the API’s id as the list key, not the index (Understanding React Keys).
Key points
- Inspect the real response, then convert it once into the shape your UI wants.
- Use optional chaining, nullish coalescing and list defaults so missing data does not crash the page.
- Format dates and money with
Intl, and never inject API HTML without sanitising it.