Skip to content

JSX is JavaScript with an attitude ​

Coming from Vue templates, JSX feels like someone removed the guardrails and said "just write JS". They're not wrong.

JSX looks like HTML in your .tsx file. It isn't HTML. It's syntax sugar for React.createElement(…) (or the modern JSX transform). That means you can use real JavaScript expressions everywhere.

The basics that trip Vue folks ​

tsx
const name = 'Lukasz'
const el = <h1 className="title">Hello, {name}</h1>

Comments for the code above:

  • className not class (because class is reserved in JS)
  • htmlFor not for on labels
  • Curly braces {…} embed expressions - like but one layer of braces
  • Self-closing tags required: <img />, <input />

Conditionals - no v-if ​

Vue:

vue
<p v-if="user">Hi, {{ user.name }}</p>
<p v-else>Please log in</p>

React:

tsx
{user ? <p>Hi, {user.name}</p> : <p>Please log in</p>}

Or early return:

tsx
if (!user) {
  return <p>Please log in</p>
}
return <p>Hi, {user.name}</p>

As you can see - it's just JS. && works for "show or nothing":

tsx
{isAdmin && <AdminPanel />}

Watch out: {count && <Badge />} is weird when count is 0 (you render 0). Prefer {count > 0 && <Badge />} or a ternary.

Lists - no v-for ​

tsx
const items = ['Vue', 'React', 'Svelte']

ul = (
  <ul>
    {items.map((item) => (
      <li key={item}>{item}</li>
    ))}
  </ul>
)

Comments for the code above:

  • .map() instead of v-for
  • key is required (same job as Vue's :key)
  • Don't use array index as key if the list reorders - same rule as Vue

Styles and attributes ​

Inline style is an object, not a string:

tsx
<div style={{ marginTop: 8, backgroundColor: 'tomato' }} />

CamelCase CSS properties. Pixel numbers can be bare numbers (8 → 8px).

Boolean attributes:

tsx
<button disabled={isLoading}>Save</button>

Fragments ​

Vue templates need a single root (or multiple with Vue 3 fragments). In React, multiple roots need a Fragment:

tsx
function TitleBlock() {
  return (
    <>
      <h1>Title</h1>
      <p>Subtitle</p>
    </>
  )
}

<>…</> is short for <React.Fragment>.

What I'd avoid at the start ​

  • Giant IIFEs inside JSX - extract a variable or a small component
  • Putting half your business logic in the return - compute above, render below

Once JSX clicks, components and props feel almost cozy. That's next.

Enjoy!