Skip to main content
Back to module
React Fundamentals · Components and Props

JSX and rendering

Reading38mLesson 2 of 3 in this module

Write JSX, render conditionally, and turn arrays of data into lists of elements with stable keys.

Why it matters

JSX is the syntax you will write in every React component. It looks like HTML, but it is JavaScript underneath, and a few rules follow from that. Most React beginner bugs, such as a missing key, class instead of className or a stray object in the markup, come from not knowing what JSX really is.

JSX is JavaScript

This line:

const heading = <h1 className="title">Hello, {name}!</h1>;

is compiled (by Babel or a similar tool) into a plain function call:

const heading = React.createElement("h1", { className: "title" }, "Hello, ", name, "!");

The result is a React element: a small object describing what to show, not a real DOM node. React later turns the tree of elements into DOM. Because JSX is an expression, you can store it in variables, return it from functions and put it in arrays.

The rules that follow

  1. One parent. A component returns one element. Wrap siblings in a <div> or an empty fragment <>...</> that adds nothing to the page.
  2. Close every tag. <img />, <br />, <input />.
  3. camelCase attributes. className (not class), htmlFor (not for), onClick, tabIndex. Inline styles take an object: style={{ color: "red" }}.
  4. Curly braces hold JavaScript expressions. {user.name}, {price * 2}, {formatDate(d)}. Statements such as if or for cannot go inside braces.
  5. Component names start with a capital letter. <BookList /> is your component; <booklist /> would be treated as an unknown HTML tag.

Conditional rendering

Since you cannot put if inside JSX, use plain JavaScript around it or an expression inside it:

function Status({ online }) {
  if (!online) {
    return <p>Offline</p>; // early return
  }
  return <p>Online</p>;
}

// Inside JSX:
<p>{count > 0 ? `${count} new messages` : "No new messages"}</p>
{isAdmin && <button>Delete</button>}

Careful with && and numbers: {items.length && <List />} renders a literal 0 when the list is empty. Write {items.length > 0 && <List />}.

React renders strings and numbers. It skips null, undefined, true and false, which is why && works. It throws an error if you try to render a plain object such as {user}; render {user.name} instead.

Turning data into elements

Real interfaces are mostly lists: products, messages, search results. You turn an array of data into an array of elements with map:

const books = [
  { id: 1, title: "Dune", author: "Frank Herbert" },
  { id: 2, title: "Kindred", author: "Octavia E. Butler" },
];

function BookList({ books }) {
  return (
    <ul>
      {books.map((book) => (
        <li key={book.id}>
          <strong>{book.title}</strong> by {book.author}
        </li>
      ))}
    </ul>
  );
}

{ books } in the parameter list reads the books value passed in as <BookList books={books} />. That is a prop, covered fully in the next lesson.

You can also filter or sort first. Use a copy before sorting, because sort changes the array in place: [...books].sort(...).

Keys

Each item in a list needs a key: a string or number that is unique among its siblings and stable over time. React uses keys to match items between renders, so when you insert, delete or reorder items it can keep each item's DOM and state attached to the right data.

  • Good keys: database IDs, slugs, anything that belongs to the item.
  • Risky keys: the array index. If the list is reordered or filtered, index 0 now points at different data, and inputs or animations can attach to the wrong row. Index keys are acceptable only for static lists that never change order.
  • Never generate keys during render with Math.random(): every render gets new keys, so React rebuilds every item.

The key goes on the outermost element returned from map, not on something inside it. React warns in the console ("Each child in a list should have a unique key prop") when one is missing.

Common mistakes

  • Returning two sibling elements without a wrapper or fragment.
  • Writing class= or for=; React warns and you should use className and htmlFor.
  • Forgetting to return inside a map callback with curly braces: books.map((b) => { <li>{b.title}</li> }) returns undefined. Use parentheses or an explicit return.
  • Putting the key on an inner element instead of the one map returns.

Recap

  • JSX compiles to React.createElement calls that create element objects.
  • Use {} for expressions, className, closed tags and one root element (or a fragment).
  • Use early returns, ? : and && for conditions.
  • Use map to turn arrays into elements, with a stable, unique key on each item.

Try it

Open the Do tab. You will finish a BookList component that turns an array of books into list items with keys, and shows a message when the array is empty.

Also in this lesson: