Lesson 6
Universal Reactivity and State Inspection in Svelte
Introduction to Universal Reactivity in Svelte

Welcome to this lesson on Universal Reactivity and State Inspection in Svelte. By now, you are already familiar with Svelte’s $state and $derived runes, which allow you to manage reactivity efficiently within components. In this lesson, we will focus on leveraging these tools to create universal reactivity, enabling shared state across multiple components.

Universal reactivity allows state to be defined and accessed outside of individual components, making it possible to manage application-wide data in a modular and scalable way. Additionally, you will learn how to use the $inspect rune to track state changes, which is essential for debugging and gaining insights into your application's reactivity flow. By the end of this lesson, you will be able to build applications with shared reactive state while effectively monitoring and debugging state transitions.

Creating a Reactive Cart Store

Let's start by setting up a reactive cart store using Svelte's $state and $derived. This will form the backbone of our application, allowing us to manage the items in a shopping cart and keep track of the total number of items.

In the cartStore.svelte.ts file, we define two exports: cartItems and totalItems. cartItems is initialized as an empty array using $state, which makes it reactive. This means any changes to cartItems will automatically trigger updates in the UI. totalItems is a derived value, calculated using $derived to reflect the length of cartItems.

TypeScript
1export let cartItems = $state([]); 2let totalItems = $derived(cartItems.length); 3export const getTotalItems = () => totalItems;

With this setup, cartItems will hold the list of items in the cart, and totalItems will always show the current number of items. Since Svelte does not allow direct export of $derived values, we use the getTotalItems function to retrieve totalItems, ensuring it stays reactive and up-to-date. This reactive store will be used by other components to display and update the cart's contents.

Using Getters and Setters for State Management

For mutable exported states like discount, where we expect a new value to be passed, we need to use getter and setter functions. This ensures controlled updates and prevents unintended modifications.

TypeScript
1let discount = $state(0); // New state for discount 2 3export const setDiscount = (val: number) => { 4 discount = val; 5}; 6 7export const getDiscount = () => discount;

By using setters for state values like discount, we ensure that state updates are properly managed, keeping reactivity intact while maintaining control over modifications.

Usage in a component:

svelte
1<script lang="ts"> 2 import { setDiscount, getDiscount } from '$lib/cartStore.svelte.ts'; 3 4 function applyDiscount() { 5 setDiscount(10); 6 } 7</script> 8 9<p>Current Discount: {getDiscount()}</p> 10<button onclick={applyDiscount}> 11 Apply $10 Discount 12</button>
Building a Reactive Cart Button

Next, we will create a CartButton.svelte component that allows users to add items to the cart. This component will import cartItems from our cart store and provide a function to add new items.

In the CartButton.svelte file, we define an addItem function that takes an item as a parameter and updates cartItems by appending the new item. Additionally, we use $inspect to track state changes automatically.

svelte
1<script lang="ts"> 2 import { cartItems, setDiscount, getDiscount } from '$lib/cartStore.svelte.ts'; 3 4 function addItem(item: string): void { 5 cartItems.push(item); 6 setDiscount(cartItems.length * 5); // Apply a discount based on item count 7 } 8 9 $inspect(cartItems, "Cart Items State"); 10</script> 11 12<p>Current Discount: {getDiscount()}</p> 13<button onclick={() => addItem("Item " + (cartItems.length + 1))}> 14 Add Item ({cartItems.length}) 15</button>

When the button is clicked, a new item is added to the cart, and the button's label updates to reflect the current number of items. Additionally, a discount is applied dynamically based on the number of items in the cart. This demonstrates Svelte's reactivity in action, as the UI automatically updates in response to changes in cartItems.

How $inspect Works

Instead of writing manual console.log statements inside every function that updates the state, $inspect automatically logs the current value of cartItems whenever it changes.

Console output after adding two items:
Less
1Cart Items State: ["Item 1"] 2Cart Items State: ["Item 1", "Item 2"]

No extra console.log is needed—Svelte automatically tracks updates!

Displaying Cart Summary with State Inspection

Now, let's create a CartSummary.svelte component to display the total number of items and list the items in the cart. This component will import both getTotalItems and cartItems from the cart store.

In the CartSummary.svelte file, we use Svelte's template syntax to display totalItems and iterate over cartItems using the #each block. This allows us to dynamically render a list of items in the cart. The use of $inspect in the previous component helps us verify that the state updates are working as expected.

svelte
1<script lang="ts"> 2 import { getTotalItems, cartItems } from '$lib/cartStore.svelte.ts'; 3</script> 4 5<p>Total Items: {getTotalItems()}</p> 6<ul> 7 {#each cartItems as item (item)} 8 <li>{item}</li> 9 {/each} 10</ul>

This component provides a clear summary of the cart's contents, showcasing the power of Svelte's reactivity and state management features.

Integrating Components in the Main Application

Finally, we will integrate the CartButton and CartSummary components into the main application. This will allow us to see the complete functionality in action.

In the App.svelte file, we import both components and include them within the main section of the application. This setup ensures that the button and summary are displayed together, providing a cohesive user experience.

svelte
1<script lang="ts"> 2 import CartButton from '$lib/CartButton.svelte'; 3 import CartSummary from '$lib/CartSummary.svelte'; 4</script> 5 6<main> 7 <CartButton /> 8 <CartSummary /> 9</main>

With this integration, you can add items to the cart and see the summary update in real-time, demonstrating the seamless reactivity provided by Svelte.

Summary and Preparation for Practice

In this lesson, you have learned about Svelte's universal reactivity and state inspection features. We explored how to use $state and $derived to manage and inspect state changes, creating a reactive cart store and components to interact with it. These concepts are crucial for building dynamic applications that respond to user interactions efficiently.

As you move forward, practice exercises will reinforce your understanding and help you gain confidence in using these features in Svelte. Keep experimenting with the code examples and apply these concepts to your own projects. You're doing great, and I look forward to seeing what you create!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.