Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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.

Thanks for reading!

Donate to the site — we work hard for you.