Learn / Frameworks / React / JSX and Components

Beginner 15 min

JSX and Components

Write JSX, compose components and pass data down with props.

What you will learn

  • Write valid JSX
  • Pass and destructure props
  • Use children

JSX is a syntax that lets you write HTML-like markup inside JavaScript. A build tool converts it to ordinary function calls. It is not a template language: it is JavaScript, so you have the full language available inside curly braces.

JSX rules

  • A component returns one root element. Wrap siblings in a <div> or a fragment <>...</>.
  • Close every tag, including <img /> and <br />.
  • Use className instead of class, and htmlFor instead of for.
  • Attributes are camelCase: onClick, tabIndex.
  • Put JavaScript expressions in { }. Style takes an object: style={{ color: "red" }}.
function Profile() {
  const user = { name: "Ada", age: 36 };
  const year = new Date().getFullYear();
  return (
    <>
      <h2 className="title">{user.name}</h2>
      <p>Born around {year - user.age}</p>
    </>
  );
}

Props

Props are how a parent passes data to a child, exactly like function arguments. They arrive as one object, so destructure them in the parameter list. Props are read-only: a component must never change its own props.

function Greeting({ name, excited = false }) {
  return <h1>Hello, {name}{excited ? "!" : "."}</h1>;
}

function App() {
  return (
    <>
      <Greeting name="Ada" excited />
      <Greeting name="Linus" />
    </>
  );
}

Strings can be written in quotes; everything else (numbers, booleans, arrays, objects, functions) goes in braces: <Card count={3} tags={["a", "b"]} />.

Children and composition

Anything placed between a component's tags arrives as the special children prop, letting you build wrapper components.

function Card({ title, children }) {
  return (
    <section className="card">
      <h3>{title}</h3>
      {children}
    </section>
  );
}

<Card title="Tip">
  <p>Small components are easier to reuse.</p>
</Card>;
function Status({ online, unread }) {
  if (!online) return <p>Offline</p>;
  return (
    <p>
      Online {unread > 0 && <strong>({unread} new)</strong>}
    </p>
  );
}
Common bug

{count && <X />} renders the number 0 when count is 0. Write {count > 0 && ...} instead.

Try it yourself

Create a Button component that takes label and an optional variant prop ("primary" by default) and renders a button whose className includes the variant.

Show solution
function Button({ label, variant = "primary" }) {
  return <button className={`btn btn-${variant}`}>{label}</button>;
}

<Button label="Save" />;
<Button label="Delete" variant="danger" />;