Component
In Svelte, a component is a reusable and independent UI block.
It is the basic unit used to build a user interface.
One of the most important concepts in Svelte components is Props. Props in Svelte are a mechanism to pass data from a parent component to a child component. They allow parent components to send information to child components, making the child components dynamic and reusable.
The structure overview
In the child component (e.g., Child.svelte
), use the export let
syntax to declare a prop.
1
2
3
4
5
6
| <!-- $lib/components/Child.svelte -->
<script>
export let name;
</script>
<p>Hello, {name}!</p>
|
In the parent component (e.g., App.svelte
), pass the value to the child:
1
2
3
4
5
6
| <!-- /src/routes/+page.svelte -->
<script>
import Child from '$lib/components/Child.svelte';
</script>
<Child name="DS2Man" />
|
1
2
| # Result is ...
Hello, DS2Man!
|
Examples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| <script>
// Import child components
// FruitName.svelte: displays fruit name only
// Fruit.svelte: displays fruit name and color
import FruitName from '$lib/components/Fruit_name.svelte';
import Fruit from '$lib/components/Fruit.svelte';
// Array of fruit names (used in Case 1)
let fruits_name = ['Apple', 'Banna', 'Cherry', 'Orange', 'Mango'];
// Array of fruit objects with id, name, and color (used in Case 2 & 3)
let fruits = [
{ id: 1, name: 'Apple', color: 'red' },
{ id: 2, name: 'Banna', color: 'yellow' },
{ id: 3, name: 'Cherry', color: 'blue' },
{ id: 4, name: 'Orange', color: 'orange' },
{ id: 5, name: 'Mango', color: 'orange' }
];
</script>
<main>
<div class="grid-container">
<!-- Case 1 -->
<div class="column">
<h3>Case 1</h3>
<ol>
{#each fruits_name as fruit_name}
<!--
Passing the variable 'fruit_name' as a prop
to the FruitName component.
Since the variable name and prop name are the same,
we can use shorthand: {fruit_name}
In FruitName.svelte, it will be received like:
export let fruit_name;
-->
<!--
<FruitName fruit_name={fruit_name} />
If the attribute name and the data (variable) name are the same,
you can simplify the code as shown below.
-->
<FruitName {fruit_name} />
{/each}
</ol>
</div>
<!-- Case 2 -->
<div class="column">
<h3>Case 2</h3>
<ul>
{#each fruits as fruit (fruit.id)}
<!--
Passing two props: 'fruit' and 'color'
to the Fruit component.
The parent passes data down to the child.
In Fruit.svelte, it will be received like:
export let fruit;
export let color;
-->
<Fruit name={fruit.name} color={fruit.color} />
{/each}
</ul>
</div>
<!-- Case 3 -->
<div class="column">
<h3>Case 3</h3>
<ul>
{#each fruits as { name, color } (name)}
<!--
Using destructuring to directly extract 'name' and 'color'
from the fruits array, and passing them as props.
This is another clean way to pass multiple props.
-->
<!--
<Fruit name={name} color={color} />
If the attribute name and the data (variable) name are the same,
you can simplify the code as shown below.
-->
<Fruit {name} {color} />
{/each}
</ul>
</div>
</div>
</main>
<style>
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.column {
border: 1px solid black;
padding: 10px;
}
</style>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <script>
// Declare props (properties) to receive data from the parent component
// 'name' prop: will receive the fruit name
export let name
// 'color' prop: will receive the fruit color
export let color
</script>
<main>
<li style="color: {color};">{name}</li>
</main>
<style>
</style>
|
1
2
3
4
5
6
7
8
9
10
11
12
| <script>
// Declare props (properties) to receive data from the parent component
// 'fruit_name' prop: will receive the fruit name
export let fruit_name
</script>
<main>
<li>{fruit_name}</li>
</main>
<style>
</style>
|
Result
Store
Store is a state management system provided by the Svelte framework. It allows you to store state values that can be accessed and shared globally across components.
Problem Examples
The components App.svelte
, Parent.svelte
, and Child.svelte
are properly using props
and bind
to update the name
value in App.svelte
. There is no major issue with this structure.
However, let’s consider the following scenario:
Suppose that in Parent.svelte
, there is no need to use or manage the name
value, but in Child.svelte
, the name
value needs to be updated. With the current structure, you are forced to define and pass the name
prop in Parent.svelte
, even though it doesn’t actually need it. This leads to an unnecessary and redundant structure. Furthermore, as the number of components grows, this issue becomes more serious and can cause increased complexity in your component hierarchy.
This issue can be improved by using a store.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <!-- +/src/routes/+page.svelte -->
<script>
import Parent from '$lib/components/Parent.svelte'
let name = "DS2Man"
</script>
<main>
<h1>Hello, {name}</h1>
<Parent bind:name={name}/>
</main>
<style>
</style>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| <!-- $lib/components/Parent.svelte -->
<script>
import Child from '$lib/components/Child.svelte'
export let name
let isActive = true
const toggle = () => {
if (isActive === true)
name="Parent"
else
name="DS2Man"
isActive = !isActive
}
</script>
<main>
<button on:click={toggle}>Parent!</button>
<Child bind:name={name} />
</main>
<style>
</style>
|
1
2
3
4
5
6
7
8
9
10
11
| <!-- $lib/components/Child.svelte -->
<script>
export let name
</script>
<main>
<button on:click={() => {name="Child"}}>Child!</button>
</main>
<style>
</style>
|
Solution : Using a Svelte Store
To solve this problem, we can use Svelte’s store system.
A store in Svelte is a simple and reactive way to manage and share state outside of the component hierarchy.
This allows any component to access and update shared data directly, without having to pass it through intermediate components.
In our example, we created a writable store named name
and used it in App.svelte
, Parent.svelte
, and Child.svelte
.
1
2
3
4
5
6
7
8
| // $lib/stores/Store.ts
// Import writable store from Svelte's store module
import { writable } from 'svelte/store';
// Create a writable store named 'name'
// It holds a string value and can be updated
export let name = writable('DS2Man');
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| <!-- /src/routes/+page.svelte -->
<script>
import Parent from '$lib/components/Parent.svelte'
import { name } from '$lib/stores/Store.ts'
</script>
<main>
<!--
To read a store value, use the $ prefix.
Here, $name will automatically update whenever the store value changes.
-->
<h1>Hello, {$name}</h1>
<Parent />
</main>
<style>
</style>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| <!-- '$lib/components/Parent.svelte -->
<script>
import Child from '$lib/components/Child.svelte'
import { name } from '$lib/stores/Store.ts'
let isActive = true
const toggle = () => {
if (isActive === true)
// $name="Parent"
name.set("Parent")
else
// $name="DS2Man"
name.set("DS2Man")
isActive = !isActive
}
</script>
<main>
<button on:click={toggle}>Parent!</button>
<Child />
</main>
<style>
</style>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <!-- '$lib/components/Child.svelte -->
<script>
import { name } from '$lib/stores/Store.ts' // Import the 'name' store
</script>
<main>
<!--
When this button is clicked, the store value will be updated to "Child".
All components using $name will automatically update.
-->
<button on:click={() => {name.set("Child")}}>Child!</button>
</main>
<style>
</style>
|
Result