Welcome to the first lesson of the "Component Communication & Events in Svelte" course. In this lesson, we will focus on component communication, specifically how to pass data from a parent component to a child component using props.
Props (short for "properties") are a way to share data between components. Think of props as passing a note from one person to another—the parent component writes the note (data), and the child component reads it. This is a fundamental concept in Svelte and is essential for building scalable and maintainable applications.
In this lesson, we’ll explore how to define and pass props, including complex data types like objects, and how to use them effectively in your components. By the end, you’ll be able to pass data from a parent component to a child component, just like in the example.
To pass data from a parent component to a child component, you first need to define the props in the child component. In Svelte 5, you can use the $props()
function to access the props passed from the parent.
Let’s start with a simple example: passing a string prop.
svelte1<!-- Parent.svelte --> 2<script> 3 import Child from './Child.svelte'; 4</script> 5 6<Child placeholder="Enter your name" />
svelte1<!-- Child.svelte --> 2<script> 3 let { placeholder } = $props(); 4</script> 5 6<input type="text" placeholder={placeholder} />
In this example, the parent component (Parent.svelte
) passes a placeholder
prop to the child component (Child.svelte
). The child component extracts placeholder
from $props()
and applies it to the <input>
field. When you run this code, the input field will display the placeholder text "Enter your name."
In
Svelte
, the$props()
function allows a child component to access props passed from its parent. However, it’s important to note that$props()
itself does not trigger reactivity. When a parent component updates a prop, the child component receives the new value, but the$props()
function doesn’t automatically cause a reactive update like$state
. To ensure that changes to props are properly tracked within the child component, you can either destructure the needed values or assign them to$state
. This approach helps maintain reactivity and ensures your components stay in sync with their data sources.
In some cases, a component may need to accept additional props dynamically without explicitly defining each one. This is useful when creating wrappers around elements like <input>
, <button>
, or <a>
tags.
To achieve this, you can use the rest syntax (...rest
) to collect all extra props and forward them.
svelte1<!-- Parent.svelte --> 2<script> 3 import InputField from './InputField.svelte'; 4</script> 5 6<InputField label="Username" type="text" placeholder="Enter username" required />
svelte1<!-- InputField.svelte --> 2<script> 3 let { label, ...rest } = $props(); 4</script> 5 6<label> 7 {label} 8 <input {...rest} /> 9</label>
In this example:
- The parent component passes multiple props (
label
,type
,placeholder
,required
). - The child component extracts only
label
, while...rest
gathers all other props. - These extra props are spread onto the
<input>
element, ensuring it automatically receives all attributes passed from the parent.
This technique allows components to remain flexible and reusable, making it easy to support any additional attributes without needing explicit definitions.
Props aren’t limited to simple data types like strings—you can also pass objects, arrays, and more. Let’s expand on our previous example by passing a user object alongside additional props.
svelte1<!-- Parent.svelte --> 2<script> 3 import Child from './Child.svelte'; 4 5 let user = $state({ name: "Alice" }); 6 7 function changeName(name) { 8 user.name = name; 9 } 10</script> 11 12<input type="text" oninput={(e) => changeName(e.target.value)} value={user.name}> 13<Child {user} placeholder="Enter your name" lastName="Smith" />
svelte1<!-- Child.svelte --> 2<script> 3 let { user, placeholder, lastName } = $props(); 4</script> 5 6<p>User: {user.name}</p> 7<p>Placeholder: {placeholder}</p> 8<p>Last Name: {lastName}</p>
Now, when you type in the input field, the user.name
updates in real time. Since the user
object is reactive in the parent, the child component automatically reflects the changes, demonstrating how props remain linked to parent state. This is an important aspect of Svelte’s reactivity model, ensuring that when the parent updates a prop, the child receives the latest value.
Note: Props should never be modified inside a child component. Since props are passed from parent to child, changes should always be made in the parent component and propagated down.
When working with props, it’s important to follow best practices to maintain clean and efficient components:
-
Use
...rest
for flexibility
If a component needs to accept arbitrary attributes,...rest
makes it adaptable and scalable. -
Avoid overloading components with too many props
Keep prop usage minimal and focused on the component’s purpose. -
Mutating Props Directly in the Child Component
Props should be treated as read-only in the child component. If you need to modify the data, consider passing a callback function or using a reactive state in the parent component. -
Best Practices
- Use descriptive prop names to make your code more readable.
- Keep props minimal and focused on the component’s purpose.
- Use objects to group related props together, making it easier to pass and manage them.
In this lesson, you learned:
- How to define and pass props using
$props()
. - How to forward extra props dynamically using
...rest
. - How to pass complex data like objects between components.
- Best practices for scalable, maintainable component communication.
These concepts are essential for building reusable components in Svelte. In the next exercises, you’ll apply what you’ve learned by dynamically passing props and handling data efficiently!