Embedding Expressions in JSX
The Curly Brace Syntax
A JSX expression interpolation looks exactly like a template literal interpolation, but works inside markup rather than a string:
const name = 'Alice'
const age = 30
function Profile() {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Born in: {new Date().getFullYear() - age}</p>
</div>
)
}The value of {name} is substituted at render time. React then converts that value to a string and inserts it into the DOM. Numbers, strings, JSX elements, and arrays are all valid. null, undefined, and false render nothing (they are silently skipped).
What Can Go Inside Curly Braces
Any JavaScript expression is valid — that is, any code that evaluates to a single value:
Expression type | Example | Notes |
|---|---|---|
Variable | {username} | Most common usage |
Arithmetic | {price * quantity} | Evaluates to a number |
String method | {title.toUpperCase()} | Any method call returning a value |
Function call | {formatDate(createdAt)} | Must return something renderable |
Ternary | {isLoggedIn ? <UserNav /> : <GuestNav />} | Inline conditional |
Logical && | {hasItems && <CartBadge count={items.length} />} | Short-circuit render |
Template literal | { | Useful for composite strings |
Array.map() | {items.map(i => <li key={i.id}>{i.name}</li>)} | Renders a list |
Nullish coalescing | {nickname ?? username} | Fallback value |
Optional chaining | {user?.profile?.bio} | Safe property access |
Variables and Simple Values
function ProductCard({ product }) {
const discountedPrice = product.price * (1 - product.discount)
const formattedPrice = discountedPrice.toFixed(2)
return (
<div className="card">
<h3>{product.name}</h3>
<p>{product.description}</p>
<span className="price">${formattedPrice}</span>
<span className="stock">
{product.stock} units left
</span>
</div>
)
}Function Calls
You can call any function inside curly braces, as long as it returns something React can render. Helper functions computed before the return statement are often cleaner, but inline calls work fine for simple transformations:
function formatDate(dateString) {
return new Intl.DateTimeFormat('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric',
}).format(new Date(dateString))
}
function Article({ title, publishedAt, author }) {
return (
<article>
<h1>{title}</h1>
<time dateTime={publishedAt}>
Published {formatDate(publishedAt)}
</time>
<p>By {author.name.toUpperCase()}</p>
</article>
)
}Ternary Expressions for Conditionals
The ternary operator condition ? valueIfTrue : valueIfFalse is the go-to for inline conditional rendering. Both branches can be JSX, strings, numbers, or null:
function StatusBadge({ isActive }) {
return (
<span className={isActive ? 'badge badge--active' : 'badge badge--inactive'}>
{isActive ? 'Active' : 'Inactive'}
</span>
)
}
// Ternary can render entire components
function AuthSection({ user }) {
return (
<header>
<Logo />
{user ? <UserMenu user={user} /> : <LoginButton />}
</header>
)
}Logical AND for Optional Rendering
When you only want to render something if a condition is true — and render nothing otherwise — the logical && operator is concise:
function Notifications({ count }) {
return (
<div>
<BellIcon />
{count > 0 && <span className="badge">{count}</span>}
</div>
)
}Template Literals for Composite Strings
function UserGreeting({ firstName, lastName, isPremium }) {
const fullName = `${firstName} ${lastName}`
const plan = isPremium ? 'Premium' : 'Free'
return (
<div>
<h2>Welcome back, {fullName}!</h2>
<p className={`plan plan--${plan.toLowerCase()}`}>
{plan} Plan
</p>
</div>
)
}Rendering Lists with map()
Embedding an Array.map() call is the standard way to render a list of items. Each element returned by map() should have a unique key prop (covered in its own page):
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id} className={todo.done ? 'done' : ''}>
{todo.text}
</li>
))}
</ul>
)
}What CANNOT Go Inside Curly Braces
JavaScript statements are not expressions — they do not return a value and therefore cannot appear inside JSX curly braces:
// ❌ if statement — not an expression
function Broken({ isAdmin }) {
return (
<div>
{if (isAdmin) { <AdminPanel /> }} // SyntaxError
</div>
)
}
// ❌ for loop — not an expression
function AlsoBroken({ items }) {
return (
<ul>
{for (const item of items) { <li>{item}</li> }} // SyntaxError
</ul>
)
}
// ✅ Correct approach for if: ternary or pre-computed variable
function FixedConditional({ isAdmin }) {
const panel = isAdmin ? <AdminPanel /> : null
return <div>{panel}</div>
}
// ✅ Correct approach for loops: map()
function FixedList({ items }) {
return (
<ul>
{items.map((item) => <li key={item}>{item}</li>)}
</ul>
)
}Expressions in Attribute Values
const imageUrl = '/photos/avatar.png'
const altText = 'User avatar'
const isDisabled = false
// ✅ Dynamic attribute values
<img src={imageUrl} alt={altText} />
<button disabled={isDisabled}>Click me</button>
<div className={`container ${isWide ? 'container--wide' : ''}`}>
// ❌ Do not mix quotes and braces
<img src="{imageUrl}" /> // Renders the literal string "{imageUrl}"Summary
Use
{}to embed any JavaScript expression into JSX markup or attribute valuesVariables, arithmetic, method calls, ternaries, template literals, and
map()are all validStatements (
if,for,while) cannot go inside{}— compute them beforereturnor use expression equivalentsnull,undefined, andfalserender nothing — useful for conditional renderingWatch out for
{count && ...}whencountmight be0— use{count > 0 && ...}insteadAttribute values use
{expression}not"{expression}"— the quotes and braces are mutually exclusive