Svelte and SvelteKit course · Module 4: Props and Events
Advanced Props
In this lesson5
Rest Props
Collect remaining props into an object:
<script>
// Extract name and weapon, collect the rest into 'rest'
let { name, weapon, ...rest } = $props();
</script>
<div class="warrior" {...rest}>
<h3>{name}</h3>
<p>Weapon: {weapon}</p>
</div><!-- Usage - class, id and data-rank go into 'rest' -->
<Warrior
name="Ragnar"
weapon="Axe"
class="elite"
id="warrior-1"
data-rank="jarl"
/>Shorthand Syntax
When the variable name = prop name:
<script>
import Warrior from './Warrior.svelte';
let name = 'Ragnar';
let strength = 95;
</script>
<!-- Full syntax -->
<Warrior name={name} strength={strength} />
<!-- Shorthand syntax -->
<Warrior {name} {strength} />Props as Snippets (Svelte 5)
The content between a component's tags arrives in the children prop, and you define named fragments with a {#snippet} block. The component shows them with the {@render} tag (in Svelte 4 slots did this, <slot />):
<!-- Card.svelte -->
<script>
let { header, children } = $props();
</script>
<div class="card">
<header>{@render header()}</header>
<main>{@render children()}</main>
</div><!-- Usage -->
<Card>
{#snippet header()}
<h2>Card header</h2>
{/snippet}
<p>Card content</p>
</Card>Reactive Props
Props are automatically reactive:
<!-- Parent.svelte -->
<script>
import Barracks from './Barracks.svelte';
let warriorCount = $state(5);
</script>
<Barracks count={warriorCount} />
<button onclick={() => warriorCount++}>Add</button><!-- Barracks.svelte -->
<script>
let { count } = $props();
// count updates automatically when it changes in the parent!
let doubled = $derived(count * 2);
</script>
<p>Warriors: {count}, Doubled: {doubled}</p>Runtime Props Validation
<script>
let { name, strength = 50 } = $props();
// Logs strength to the console on every change (development mode only)
$inspect(strength);
$effect(() => {
if (strength < 0 || strength > 100) {
console.warn(`Invalid strength: ${strength}`);
}
});
</script>Code for this lesson: App.svelte
<script>
// Advanced props: spread {...warrior} and a callback prop
import WarriorCard from './WarriorCard.svelte';
let warriors = $state([
{ id: 1, name: 'Ragnar', role: 'Berserker', level: 45 },
{ id: 2, name: 'Lagertha', role: 'Shieldmaiden', level: 42 },
{ id: 3, name: 'Bjorn', role: 'Viking', level: 38 }
]);
function levelUp(id) {
const warrior = warriors.find(w => w.id === id);
// Deep $state: changing a field updates every card that shows it
warrior.level += 1;
}
</script>
<main class="hall">
<h1>Warriors Hall</h1>
<p>{'{...warrior}'} passes every field of the object as a prop</p>
<div class="grid">
{#each warriors as warrior (warrior.id)}
<WarriorCard {...warrior} onLevelUp={levelUp} />
{/each}
</div>
</main>
<style>
.hall {
font-family: 'Georgia', serif;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
background: #1a0f0a;
color: #e8d5b7;
min-height: 100vh;
}
h1 {
color: #d4af37;
text-align: center;
}
p {
text-align: center;
color: #8b7355;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
margin-top: 2rem;
}
</style>Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. How do you use the shorthand syntax when the variable name matches the prop name?
2. How do you pass all of an object's properties as props?