Components and layouts
Pass component props
Give a component values from its parent and read them through Astro.props.
Props are how a parent passes values into a component. If you know React, Vue, or Svelte, the concept is the same, and Astro components support it too.
At the call site, props look like HTML attributes:
<Hello name="Flavio" />
Inside src/components/Hello.astro, the values arrive on Astro.props. You can read them directly in the template:
<p>Hello {Astro.props.name}!</p>
That works, but the common style is to destructure props into variables in the component script. It keeps the template clean when a component takes several values, and it gives you one place to set defaults:
---
const { name, message = 'Hello' } = Astro.props
---
<p>{message} {name}!</p>
The message = 'Hello' part is a default for a prop that might be unset. <Hello name="Flavio" /> renders “Hello Flavio!”, while <Hello name="Flavio" message="Welcome" /> renders “Welcome Flavio!”.
Quoted attributes are always strings. To pass anything else — a boolean, a number, an array, an object — use braces, which accept a JavaScript expression:
<Card title="First post" featured={post.isFeatured} />
Inside Card.astro, that value keeps its real type, so you can use it in logic, for example toggling a class:
---
const { title, featured = false } = Astro.props
---
<article class:list={{ featured }}>
<h2>{title}</h2>
</article>
Watch the quoting mistake here. featured="true" passes the string "true", not a boolean. The string is truthy, so the class still appears, but any comparison like featured === true fails. When the value is not text, use braces.
Props flow one way, from parent to child. The parent owns the data and the child owns its presentation. They are available while Astro renders the component; they do not create reactive browser state, so changing a value later in client-side code will not rerender anything.
Use a default for an optional prop, as with featured = false. For required values, fail clearly during development instead of silently rendering an empty heading. In the next lesson, TypeScript makes that contract explicit with a typed Props interface.
Lesson completed