Appearance
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:
classNamenotclass(becauseclassis reserved in JS)htmlFornotforon labels- Curly braces
{…}embed expressions - likebut 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 ofv-forkeyis 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!