Skip to content
Laviyx Learn

Try

React course menu

JSX in React: Syntax, Expressions and Rules

Learn JSX, the HTML-like syntax of React: embedding JavaScript expressions with curly braces, attributes like className and style, returning a single root with fragments, self-closing tags, comments, and how JSX compiles to JavaScript.

Beginner7 min readUpdated
On this page

JSX lets you write HTML-like markup inside JavaScript. It is how React components describe what to show.

JSX
const heading = <h1 className="title">Welcome</h1>;

JSX is not HTML and not a string. A build tool (Vite, Next.js) compiles it into ordinary JavaScript function calls that create React elements. The line above becomes roughly:

JavaScript
const heading = React.createElement("h1", { className: "title" }, "Welcome");

You could write createElement calls yourself, but JSX is far easier to read, so everyone uses it.

JavaScript inside JSX with curly braces#

Put any JavaScript expression (something that produces a value) inside { }:

JSX
export default function App() {
  const name = "Priya";
  const price = 499;
  const quantity = 3;
  const today = new Date(2026, 9, 24);

  return (
    <div>
      <h2>Hello, {name.toUpperCase()}!</h2>
      <p>Total: ₹{price * quantity}</p>
      <p>Order date: {today.toDateString()}</p>
      <p>Items in stock: {[1, 2, 3].length}</p>
    </div>
  );
}
Result

Expressions work: variables, maths, function calls, method calls, the ternary operator. Statements do not: you cannot put if, for or const inside { }. Use them before the return, or use expressions instead (see Conditional Rendering).

Attributes#

JSX attributes look like HTML, with a few differences because JSX is JavaScript:

  • class is a reserved word in JavaScript, so use className; for on labels becomes htmlFor.
  • Attributes are camelCase: onClick, tabIndex, maxLength (except aria-* and data-*, which keep their dashes).
  • String values use quotes; any other value uses braces: <img src={photoUrl} width={120} />.
  • style takes a JavaScript object with camelCase property names, so it has double braces: the outer pair for JavaScript, the inner pair for the object.
JSX
export default function App() {
  const avatarSize = 64;
  const highlight = { backgroundColor: "#fff3bf", padding: "8px 12px", borderRadius: 6 };

  return (
    <div>
      <label htmlFor="email">Email</label>{" "}
      <input id="email" type="email" placeholder="you@example.com" maxLength={40} />
      <p className="note" style={highlight}>
        Avatar size: {avatarSize}px
      </p>
      <p style={{ color: "teal", fontWeight: "bold" }}>Inline style with double braces</p>
    </div>
  );
}
Result

A number such as borderRadius: 6 is treated as pixels. {" "} adds a space between the label and the input, because JSX removes line breaks between elements.

One root element, or a fragment#

A component returns one element. To return several side by side, wrap them in a parent, or in a fragment <>...</>, which groups them without adding an extra element to the page:

JSX
export default function App() {
  return (
    <>
      <h3>Fragments</h3>
      <p>These two elements have no extra wrapper around them.</p>
    </>
  );
}
Result

Every tag must be closed#

In JSX, tags that have no content must close themselves: <img />, <input />, <br />, <hr />. Forgetting the slash is a syntax error, unlike in HTML.

Comments#

Inside JSX, comments go in braces: {/* like this */}. Outside JSX, normal JavaScript comments work.

JSX is a value#

Because JSX produces values, you can store it in variables, pass it to functions and return it from functions:

JSX
function badge(text) {
  return <span style={{ border: "1px solid #888", borderRadius: 4, padding: "0 6px" }}>{text}</span>;
}

export default function App() {
  const greeting = <strong>Good morning</strong>;
  return (
    <p>
      {greeting}, your plan is {badge("Pro")} {/* a function returning JSX */}
    </p>
  );
}
Result

Safe by default#

Text inside { } is always inserted as text, never as HTML. If a user's name is <b>hacker</b>, React shows those characters literally rather than making text bold, which protects against cross-site scripting (XSS). React has an escape hatch, dangerouslySetInnerHTML, whose name is a warning: only use it with HTML you trust or have sanitised.

Common mistakes#

Practice#

Practice exercise

Write a component that shows a product card: the name "Wireless Mouse" in an <h3>, the price 899 formatted as ₹899.00 using toFixed(2), and a green "In stock" message using an inline style.

Show hint

Store the price in a variable and write ₹{price.toFixed(2)}. For the style, pass style={{ color: "green" }}.

Show solution
JSX
export default function App() {
  const name = "Wireless Mouse";
  const price = 899;
  return (
    <div className="card">
      <h3>{name}</h3>
      <p>₹{price.toFixed(2)}</p>
      <p style={{ color: "green" }}>In stock</p>
    </div>
  );
}
Result

Key takeaway#

Next: Components.

Finished this lesson?