React: From Components to Production · Components and JSX

JSX Essentials

Write markup in JavaScript: expressions, attributes, fragments and rules.

JSX is syntax that compiles to React.createElement/jsx() calls. Rules: return a single root (use fragments <>...</>), close every tag, use className and htmlFor, camelCase event handlers (onClick), and embed JavaScript expressions in {}. Inline styles take objects. JSX escapes values by default, protecting against XSS unless you use dangerouslySetInnerHTML.

type Props = { user: { name: string; avatarUrl: string; isAdmin: boolean } };

export function UserBadge({ user }: Props) {
  const initials = user.name.split(" ").map((p) => p[0]).join("");
  return (
    <>
      <img className="avatar" src={user.avatarUrl} alt={`${user.name}'s avatar`} width={40} height={40} />
      <span style={{ fontWeight: 600 }}>{user.name}</span>
      {user.isAdmin && <span className="badge">Admin</span>}
      <span aria-hidden="true">{initials}</span>
    </>
  );
}

Common pitfalls

  • Rendering {count && <Badge />} when count is 0 — React renders 0.
  • Using dangerouslySetInnerHTML with unsanitized input.
  • Forgetting alt text on images.

Key points

  • JSX is JavaScript expressions + markup
  • Values are escaped by default
  • Use fragments for multiple roots

Further reading: react.dev: Writing markup with JSX

Practice questions

Why does {items.length && <List />} sometimes render '0'?

Answer

When items.length is 0, the expression evaluates to the number 0, which React renders. Use items.length > 0 && <List /> or a ternary.

How does JSX help prevent XSS?

Answer

React escapes strings embedded in JSX before inserting them into the DOM, so user content is treated as text. Only dangerouslySetInnerHTML bypasses this.

Open in the app to mark lessons complete, take notes and track your progress.