Part 2: Svelte 5 Reactivity and the Role of Runes

Part 2: Svelte 5 Reactivity and the Role of Runes

Importance of reactivity in web development frameworks

In today’s development world, reactivity has become an essential feature for modern web development frameworks. This is because reactivity allows the user interface to automatically update in response to changes in the application state, providing a seamless and dynamic user experience.

With reactivity, developers can create applications that are more interactive and responsive, as the framework efficiently manages the synchronization between the data model and the user interface. This means that when data changes, the UI reflects these changes instantly without requiring manual DOM manipulation.

Angular 6|7 RxJS 6 In-Depth Tutorial & Example | by WebTutPro | ITNEXT

As a result, it not only enhances the performance of web applications but also simplifies the development process by reducing the amount of code needed to keep the UI in sync with the underlying data. Consequently, frameworks that prioritize reactivity, such as Svelte, are gaining popularity among developers who seek to build efficient and user-friendly applications.

To understand how reactivity is utilized in current web development frameworks, it's important to compare how different frameworks implement this feature.

In frameworks like React, reactivity is achieved through a virtual DOM and a component-based architecture. React uses a system of state and props to manage data flow, where changes in state trigger re-renders of components, updating the UI efficiently. This approach allows developers to build complex user interfaces with a clear separation of concerns.

Vue.js takes a slightly different approach by using a reactive data-binding system. It employs a reactivity system that automatically tracks dependencies and updates the DOM when data changes. Vue's reactivity is more granular, allowing for fine-tuned updates that can improve performance in certain scenarios.

Angular, on the other hand, uses a two-way data binding mechanism, which synchronizes the model and the view. This means that any changes in the UI are immediately reflected in the model and vice versa. Angular's reactivity is deeply integrated into its framework, providing a robust solution for building large-scale applications.

Svelte offers a unique take on reactivity by compiling components into highly efficient imperative code that directly manipulates the DOM. This means that Svelte applications do not require a virtual DOM, resulting in faster updates and less overhead. Svelte's reactivity is built into the language itself, making it intuitive and easy to use for developers.

Each of these frameworks has its own strengths and weaknesses in terms of reactivity, and the choice often depends on the specific needs of the project and the preferences of the development team. By understanding these differences, developers can make informed decisions about which framework best suits their application requirements.

Introduction to Runes in Svelte 5

In the latest version of Svelte, known as Svelte 5, a groundbreaking concept called "Runes" has been introduced. This innovative feature marks a major leap forward in how developers can handle state management and reactivity in their applications. Runes provide a more powerful and flexible way to define and interact with reactive data.

They allow developers to create more complex and dynamic user interfaces with ease. By using Runes, developers can write cleaner and more maintainable code, as they offer a more intuitive approach to managing the flow of data throughout an application.

Understanding Runes Through Examples

At the time of writing this article, there are currently seven runes integrated into the Svelte 5 framework. These runes are designed to enhance the way developers interact with state and manage reactivity in their applications:

  • $state
<script>
  let counter = $state(0);

  const increment = () => {
    counter++;
  }
</script>

<button onclick={increment}>Count: {counter}</button>

  • $derived
<script>
  const price = $state(100);
  const quantity = $state(2);
  const total = $derived(price * quantity);
</script>

<div>
  <p>Price: {price}</p>
  <p>Quantity: {quantity}</p>
  <p>Total: {total}</p>
</div>

  • $effect
<script>
  // Reactive state for background color
  let backgroundColor = $state('#ffffff');

  // Synchronize the state with the document body background
  $effect(() => {
    document.body.style.backgroundColor = backgroundColor;
  });
</script>

<div style="padding: 1rem; text-align: center;">
  <label for="color-picker">Choose background color:</label>
  <input
    id="color-picker"
    type="color"
    bind:value={backgroundColor}
    style="margin-left: 0.5rem;"
  />
  <p>The current background color is: {backgroundColor}</p>
</div>

  • $props
// MessageComponent.svelte
<script>
  const { message } = $props;
</script>

<p>{message}</p>
<MessageComponent message="Hello from parent!" />
  • $bindable
<script>
  let { value = $bindable(0) }: { value: number } = $props();
</script>

<input type="number" bind:value={value} />
<p>The value is {value}</p>
<NumberInput bind:value={myValue} />
  • $inspect
<script>
  let counter = $state(0);

  $inspect(counter, 'Counter Value');
</script>

<button onclick={() => counter++)}>
  Increment
</button>
<p>Counter: {counter}</p>
  • $host
// ColorPicker.svelte
<svelte:options customElement="my-color-picker" />

<script>
  const colors = ['red', 'green', 'blue'];

  function dispatchColor(color) {
    $host().dispatchEvent(new CustomEvent('colorselect', { detail: color }));
  }
</script>

<div style="display: flex; gap: 10px;">
  {#each colors as color}
    <button
      style="background-color: {color}; width: 50px; height: 50px;"
      onclick={() => dispatchColor(color)}
    ></button>
  {/each}
</div>
// App.svelte
<script>
  import './ColorPicker.svelte';

  let selectedColor = 'none';
</script>

<my-color-picker
  oncolorselect={(event) => selectedColor = event.detail}
/>

<p>Selected color: {selectedColor}</p>
<div
  style="width: 100px; height: 100px; border: 1px solid black; background-color: {selectedColor};"
></div>

What truly sets Svelte 5 apart from other frameworks is how it implements Signals. First, they embedded them within the framework. Although this has its own drawbacks, it allows us, for example, to completely remove signals when compiling in server-side rendering mode, as they are unnecessary overhead on the server.

Conclusion

In conclusion, Svelte 5 introduces a revolutionary approach to reactivity with the introduction of Runes, offering developers a more intuitive and efficient way to manage state and data flow in their applications.

  • By eliminating the need for a virtual DOM and embedding reactivity directly into the language, Svelte 5 provides faster updates and reduced overhead, making it an attractive choice for building modern web applications.

  • The use of Runes allows for cleaner, more maintainable code and enhances the ability to create complex, dynamic user interfaces.

  • As Svelte continues to evolve, its innovative features like Runes and Signals position it as a forward-thinking framework with significant potential for future developments in web development.

In Part 1 we learn how to quickly set up a Svelte 5 project with their new CLI. Check it out!

In the next part, we will start to create a real-world example project where we’ll add features and show what can be achieved with this great framework. We’ll be working within this simple repo I created for the series: Svelte5-course.

So, stay tuned & see ya in next chapter!

Did you find this article valuable?

Support ✍️ aiherrera's Blog by becoming a sponsor. Any amount is appreciated!