JSX is the syntax you will spend most of your time writing in React. It looks like HTML sitting right inside your JavaScript, and that is intentional — it keeps the markup and the logic that drives it next to each other instead of split across separate template files.

A first component

function ProfileCard() {
  return (
    <div className="card">
      <h2>Ada Lovelace</h2>
      <p>Mathematician and writer.</p>
    </div>
  );
}

Notice className instead of class — since class is a reserved word in JavaScript, React renames the HTML attribute. This trips up almost everyone the first time they copy-paste HTML into a component.

Embedding real JavaScript values

Curly braces let you drop any JavaScript expression straight into your markup:

function ProfileCard() {
  const name = "Ada Lovelace";
  const yearsActive = 2024 - 1815;
  return (
    <div className="card">
      <h2>{name}</h2>
      <p>Active for roughly {yearsActive} years.</p>
    </div>
  );
}

Anything that is a valid JavaScript expression works inside those braces: variables, function calls, ternaries, arithmetic. Statements like if do not work directly inside JSX, which is why you will see a lot of ternary operators and short-circuit && expressions in React code once you start handling conditional rendering.

Composing components together

The real power shows up once components render other components:

function App() {
  return (
    <div>
      <ProfileCard />
      <ProfileCard />
    </div>
  );
}

Each <ProfileCard /> is a self-closing tag, the same way <img /> is in HTML. A React app is really just one big tree of components like this, starting from a root App component at the top.

A couple of JSX rules worth knowing early

  • A component must return a single root element — wrap sibling elements in a <div> or an empty <>...</> fragment.
  • Every element needs to be properly closed, including ones like <input /> that you might leave open in plain HTML.
  • Component names must start with a capital letter — profileCard would be treated as a plain HTML tag, not your component.

Next up: passing data into components with props, and giving them memory with the useState hook — that is where components actually start reacting to things.