Props: $props
Props are data a parent component passes to a child, like attributes on an HTML tag. Thanks to them one TodoItem component can show any task: the text and status come from outside. Inside the component, props are received with the $props rune.
Receiving props
Open src/lib/components/TodoItem.svelte from the lesson on components and replace its content:
<!-- src/lib/components/TodoItem.svelte -->
<script>
let { text, done } = $props();
</script>
<li>{done ? '✓' : '○'} {text}</li>$props() returns an object with all passed props, and destructuring puts them into the variables text and done.
Passing props
The parent passes values as attributes:
<!-- src/routes/+page.svelte -->
<script>
import TodoItem from '$lib/components/TodoItem.svelte';
</script>
<ul>
<TodoItem text="Buy bread" done={true} />
<TodoItem text="Call Oleg" done={false} />
</ul>The page shows two items: "✓ Buy bread" and "○ Call Oleg". A string can be passed in quotes, any other value in curly braces.
Props from a list
Usually a component is rendered in an {#each} block and receives the object's fields:
<!-- src/routes/+page.svelte -->
<script>
import TodoItem from '$lib/components/TodoItem.svelte';
let todos = $state([
{ id: 1, text: 'Buy bread', done: true },
{ id: 2, text: 'Call Oleg', done: false }
]);
</script>
<ul>
{#each todos as todo (todo.id)}
<TodoItem text={todo.text} done={todo.done} />
{/each}
</ul>If the parent changes todo.done, the child shows the new mark at once: props are reactive. A shorter form spreads the object: <TodoItem {...todo} />.
Default values
For an optional prop, set a default value right in the destructuring:
<!-- src/lib/components/TodoItem.svelte -->
<script>
let { text, done = false } = $props();
</script>
<li>{done ? '✓' : '○'} {text}</li>Now <TodoItem text="Buy bread" /> without done shows an empty circle.
Rest props
Props the component does not take by name can be collected into an object and passed on to an element:
<!-- src/lib/components/TodoItem.svelte -->
<script>
let { text, done = false, ...rest } = $props();
</script>
<li {...rest}>{done ? '✓' : '○'} {text}</li><TodoItem text="Buy bread" title="Hint" /> adds the title attribute to the li element.
Common mistake
Changing a prop inside the child component, for example done = !done on click. The change stays inside that component, the parent never learns about it, and the data gets out of sync. Data is changed by its owner — the parent. How to tell the parent about an event is covered in the next lesson.