Components and Props
Chapter 1's child components were static. Props make a component reusable by letting a parent pass data in — the same concept as React props, Vue's defineProps, and Angular's @Input. Svelte 5 declares them with the $props rune, and the result reads like plain JavaScript object destructuring.
Declaring Props with $props
let { name, age } = $props() declares the props this component accepts by destructuring them from the $props() rune. The destructured variables are then used directly in the markup ({name}), and — because $props is reactive — they automatically update if the parent passes new values. This is strikingly close to React's function UserCard({ name, age }) destructuring, just pulled from a rune instead of function parameters.
Passing Props from a Parent
Import the child, then place its tag with props as attributes. The familiar string-vs-expression rule applies, exactly as in JSX: name="Philip" passes the literal string, but age={35} (with braces) passes the real number. This is identical to React's quoting rule and the same idea as Vue's :age vs age — Svelte just uses JSX-style braces rather than a binding prefix.
Default Values
Because props are destructured, plain JavaScript default-value syntax gives a fallback when the parent omits a prop — age = 0, isAdmin = false. No special "default" option object like Vue's or Angular's; it's just destructuring defaults, the same as React's. Clean and familiar.
Rest Props and Spreading
The rest pattern (...rest) collects any props you didn't name explicitly, and {...rest} spreads them onto an element — the standard way to build a wrapper component that forwards arbitrary attributes (e.g. a custom <Button> that still accepts disabled, type, etc.). This is exactly React's {...rest} spread, working the same way.
<script lang="ts">, props get typed by annotating the destructure: let { name, age = 0 }: { name: string; age?: number } = $props(). This gives the same compile-time prop checking that Vue's typed defineProps and Angular's typed @Input provide — and that React needs PropTypes or TS for. The course stays in plain JS, but the TS path is a one-line annotation away.
Passing Objects and Arrays
Anything that isn't a plain string goes in braces — numbers, booleans, arrays, objects, functions. Note Svelte uses the JS-native inStock (camelCase) attribute name directly, with no kebab-case conversion (unlike Vue's :in-stock convention) — props are passed exactly as named.
let local = $derived(name), or a separate $state initialized from the prop); to change the parent's data, use a callback prop or event — next chapter. (There's a $bindable() rune for genuine two-way prop binding, covered alongside component bind: in Chapter 7.)
| Svelte | React | Vue | Angular |
|---|---|---|---|
| let { name } = $props() | params { name } | defineProps(['name']) | @Input() name |
| name="x" (string) | name="x" | name="x" | name="x" |
| age={35} (real value) | age={35} | :age="35" | [age]="35" |
| { age = 0 } default | destructure default | { default: 0 } | typed input + default |
| ...rest + {...rest} | ...rest spread | v-bind="$attrs" | — |
Coding Challenges
Build a MovieCard component with title and year props (via $props), rendering "Title (Year)". Use it three times in a parent with three different movies, passing year as a real number.
📄 View solutionBuild a Badge component with a text prop and a color prop defaulting to "gray". Render it once with a custom color and once without, confirming the default applies.
📄 View solutionBuild a Button wrapper component that takes a label prop and collects all other props with ...rest, spreading them onto a real button element — then use it passing label plus extra attributes like disabled and a title.
📄 View solutionChapter 6 Quick Reference
- let { name, age } = $props() — declares props by destructuring the rune (= React params)
- Used directly in markup; reactive — updates when the parent passes new values
- name="x" passes a string; prop={expr} passes a real value (braces, like JSX)
- Defaults are plain destructuring defaults:
{ age = 0 } - ...rest collects extra props; {...rest} forwards them onto an element
- Props are read-only — change parent data via a callback/event (next chapter)
- Next chapter: component communication — callback props and events