Skip to content

Expressions

Astro template expressions look almost identical to JSX. You use {expr} to embed any JavaScript expression. The critical difference: Astro evaluates them once at build/server time and writes static HTML. There is no virtual DOM, no re-renders, no reactive updates.

React
// Stats.jsx
export default function Stats({ count, label }) {
const doubled = count * 2;
return (
<div>
<span>{label}: {count}</span>
<span>Doubled: {doubled}</span>
</div>
);
}
Astro
---
// Stats.astro
const { count, label } = Astro.props;
const doubled = count * 2;
---
<div>
<span>{label}: {count}</span>
<span>Doubled: {doubled}</span>
</div>

JSX uses {condition && <El />} and ternaries. Astro uses exactly the same syntax.

React
// Alert.jsx
export default function Alert({ type, message }) {
return (
<div>
{type === "error" && (
<p className="error">{message}</p>
)}
{type !== "error" && (
<p className="info">{message}</p>
)}
</div>
);
}
Astro
---
// Alert.astro
const { type, message } = Astro.props;
---
<div>
{type === "error" && (
<p class="error">{message}</p>
)}
{type !== "error" && (
<p class="info">{message}</p>
)}
</div>

Ternaries work identically: {isLoggedIn ? <Dashboard /> : <Login />}.

React
// TagList.jsx
export default function TagList({ tags }) {
return (
<ul>
{tags.map((tag) => (
<li key={tag}>{tag}</li>
))}
</ul>
);
}
Astro
---
// TagList.astro
const { tags } = Astro.props;
---
<ul>
{tags.map((tag) => (
<li>{tag}</li>
))}
</ul>

Astro does not require a key prop on list items — there is no virtual DOM diffing. The list is rendered to HTML once and done.

Astro
---
const fruits = ["Apple", "Banana", "Cherry", "Date"];
const today = new Date().toLocaleDateString("en-US", { weekday: "long" });
const isWeekend = [0, 6].includes(new Date().getDay());
---
<html lang="en">
  <head><meta charset="utf-8" /><title>Expressions demo</title></head>
  <body style="font-family:sans-serif;padding:2rem">
    <h1>Today is {today}</h1>
    {isWeekend && <p style="color:green">It is the weekend!</p>}
    {!isWeekend && <p style="color:#555">It is a weekday.</p>}
    <h2>Fruits ({fruits.length})</h2>
    <ul>
      {fruits.map((fruit) => <li>{fruit}</li>)}
    </ul>
  </body>
</html>
You write `{items.map((i) => <li>{i}</li>)}` in an Astro template. When does this execute?
Do Astro list items rendered with `.map()` need a `key` prop?
Which expression correctly renders a paragraph only when `isAdmin` is true in an Astro template?