Learn Svelte: Connecting the Pomodoro Timer and Tasks with Props and Stores
Tags: svelte, javascript, webdev
Published: 2020-01-28 22:15:57

---
title: Learn Svelte: Connecting the Pomodoro Timer and Tasks with Props and Stores
published: true
description: Sharing my initial experience in learning Svelte getting started by creating a sample project, a pomodoro technique app. In this part we improve our pomodoro timer and connect it to our tasks.
tags: [svelte,javascript,webdev]
canonical_url: https://www.barbarianmeetscoding.com/blog/2020/01/28/learn-svelte-connecting-the-pomodoro-timer-and-tasks-with-props-and-stores
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/1ndayocmls8wg7iob21r.png
series: Learn Svelte
---

*This article was originally published on [Barbarian Meets Coding](https://www.barbarianmeetscoding.com/blog/2020/01/28/learn-svelte-connecting-the-pomodoro-timer-and-tasks-with-props-and-stores). You can often find me there and on [Twitter](https://twitter.com/vintharas).*

**[Svelte](https://svelte.dev/) is a modern web framework that takes a novel approach to building web applications by moving the bulk of its work from runtime to compile-time**. Being a compiler-first framework allows Svelte to do some very interesting stuff that is unavailable to other frameworks like disappearing from your application at runtime, or allowing for a component centered development with HTML, JavaScript and CSS coexisting within the same Svelte file in a very web standards friendly fashion.

In this series we'll follow along as I use Svelte for the first time to build an app. I'll use my go-to project[^1] to learn new frameworks: A [Pomodoro Technique](https://francescocirillo.com/pages/pomodoro-technique) app, which is a little bit more involved than a TODO list in that it has at least a couple of components (a timer and a list of tasks) that need to interact with each other.

**In this part 5 of the series we finally put everything together and integrate the pomodoro with our collection of tasks. Yihoo! Let's get started!**

> Haven't read the other articles in this series? Then you may want to take a look at this <a href="https://www.barbarianmeetscoding.com/blog/2019/12/23/discovering-svelte">list of resources for getting started with Svelte</a>, and the <a href="https://www.barbarianmeetscoding.com/blog/2019/12/27/discovering-svelte-getting-started">first</a>, <a href="https://www.barbarianmeetscoding.com/blog/2019/12/29/discovering-svelte-adding-some-tasks-and-pomodoros">second</a> and <a href="https://www.barbarianmeetscoding.com/blog/2020/01/04/discovering-svelte-creating-a-pomodoro-timer">third</a> parts of building the Pomodoro Technique app.

## Pomodoro Meets Tasks

So we have our pomodoro timer on one side, we have our list of tasks on the other. They are both living their lives independently as completely self-contained components. One can count down pomodoros, the other can manage a collection of tasks. Our next step to be able to support the Pomodoro technique is to get them to talk to each other so that a user can:

1. Select the tasks to focus on
2. Start a pomodoro and focus fiercely on that task for 25 minutes
3. Complete a pomodoro and take a rest
4. Or cancel a pomodoro and type down the reason Why

But **How can they talk to each other?** Either by sharing some state that can be passed between components through props, or by using a Svelte store.

Let's implement both solutions and discuss the pros and cons of each of them.

## Sharing State Through Props

> ### What are Svelte props?
>  <strong>props</strong> (short for <em>properties</em>) are the mechanism that Svelte uses to send data into a component. In essence, <strong>props define the interface of a component. How it interacts with the outside world.</strong></p>.

So far in the series we've barely touched on props because both the Pomodoro Timer and the list of tasks have been self contained up to this point. Now however we need for both components to communicate. Specifically:

1. We need the `TaskList` component to be able to communicate with the outside world that a task has been selected
2. We need to tell the `PomodoroTimer` which task has been selected

### Selecting a Task

So we start by updating our `TaskList` component so that a user can select a task. We define a `selectedTask` variable that will save that information:

```html
<script>
  let activeTask;
  // more code...
</script>
```

And we update the template to select a task using a new button:

```html
{#if tasks.length === 0}
  <p>You haven't added any tasks yet. You can do it! Add new tasks and start kicking some butt!</p>
{:else}
  <ul>
    {#each tasks as task}
      <li>
        <!-- NEW STUFF -->
        <button on:click={() => selectTask(task)}>&gt;</button>
        <!--- END NEW STUFF -->
        <input class="description" type="text" bind:value={task.description} bind:this={lastInput}>
        <input class="pomodoros" type="number" bind:value={task.expectedPomodoros}>
        <button on:click={() => removeTask(task)}>X</button>
      </li>
    {/each}
  </ul>
{/if}
<button class="primary" on:click={addTask}>Add a new task</button>
{#if tasks.length != 0}
  <p>
    Today you'll complete {allExpectedPomodoros} pomodoros.
  </p>
{/if}
```

Now whenever the user clicks on the `>` button we will call the `selectTask` function that sets the activeTask to the selected task:

```javascript
function selectTask(task) {
  activeTask = task;
}
```

And whenever a user removes a task we will check whether it is the `activeTask` and in that case we will clean it up:

```javascript
function removeTask(task){
  tasks = tasks.remove(task);
  if (activeTask === task) {
    selectTask(undefined);
  }
}
```

Excellent! Now we need a way to tell the user that a given task is selected. We can do that by highlighting the active task using CSS. One way to achieve this is to set the `class` attribute of the `li` element to `.active` like so:

```html
{#each tasks as task}
  <li class={activeTask === task ? 'active': ''}>
     <!-- task --->
  </li>
{/each}
```

But Svelte has a shorthand syntax that makes it more convenient to add or remove classes based on your component's state:

```html
{#each tasks as task}
  <li class:active={activeTask === task}>
     <!-- task --->
  </li>
{/each}
```

Now we need to add some styles linked to that `.active` class inside the component:

```css
  .active input,
  .active button {
    border-color: var(--accent);
    background-color: var(--accent);
    color: white;
    transition: background-color .2s, color .2s, border-color .2s;
  }
```

And finally we have a way to select a task to work on within the `TaskList.svelte` component:

<img class="center shadow-small" src="https://www.barbarianmeetscoding.com/images/il-pomodoro-svelte-select-task.gif" title="We can select Tasks!" alt="A pomodoro app with a timer and a series of tasks. The user clicks on a button and selects a task.">

### Notifying The Outside World A Task Was Selected

Excellent! The next step is to let the world outside of this component known that a task has been selected. Svelte lets us do that through event dispatching. Inside our component we can define our own domain specific events and dispatch them to our heart's content. 

A suitable event for our use case could be called `selectedTask`:

```javascript
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();

function selectTask(task) {
  activeTask = task;
  // dispatch(eventName, eventData);
  dispatch('taskSelected', {
    task: activeTask,
  });
}
```

So now, whenever the user selects a task, we'll call the `selectTask` function that will:

1. Update the active task
2. Notify the outside world that a task has been selected by dispatching a `taskSelected` event with the currently active task

In our app component we can subscribe to that new event just like we would subscribe to any other standard DOM event:

```html
<main>
  <h1>{title}</h1>
  <PomodoroTimer />
  <TaskList on:taskSelected={updateActiveTask}/>
</main>
```

The `App.svelte` component will now store its own version of the activeTask:

```html
<script>
  let title = "il Pomodoro";
  import TaskList from './TaskList.svelte';
  import PomodoroTimer from './PomodoroTimer.svelte';

  let activeTask;
  function updateActiveTask(event){
    activeTask = event.detail.task;
  }
</script>
```

That we can then send to our friend the Pomodoro Timer:

```html
<main>
  <h1>{title}</h1>
  <PomodoroTimer {activeTask} />
  <TaskList on:taskSelected={updateActiveTask}/>
</main>
```

### Pomodoro Timer Meets Active Task

But in order to do so we to define a new prop inside our `PomodoroTimer` component:

```html
<script>
export let activeTask;
</script>
```

Since it doesn't make sense for a user to be able to interact with the pomodoro timer unless there's a task that is active, we can start by disabling the pomdoro timer in such a case:

```html
<section>
  <time>
    {formatTime(pomodoroTime)}
  </time>
  <footer>
    <button 
      class="primary" on:click={startPomodoro} 
      disabled={currentState !== State.idle || !activeTask}>start</button>
    <button on:click={cancelPomodoro} 
      disabled={currentState !== State.inProgress || !activeTask}>cancel</button>
  </footer>
</section>
```

Cool!

<img class="center shadow-small" src="https://www.barbarianmeetscoding.com/images/il-pomodoro-svelte-disable-pomo.gif" title="Disabling the timer when no task is selected" alt="A pomodoro app with a timer and a series of tasks. The user clicks on a button and selects a task. When they select a task the pomodoro timer becomes active.">

Finally, we can increment the pomodoros spent in a task when we complete a pomodoro. We update the `completePomodoro` function in `PomodoroTimer.svelte` to include that functionality:

```javascript
function completePomodoro(){
  // We add one more pomodoro to the active task
  activeTask.actualPomodoros++; 
  completedPomodoros++;
  if (completedPomodoros === 4) {
    rest(LONG_BREAK_S);
    completedPomodoros = 0;
  } else {
    rest(SHORT_BREAK_S);
  }
}
```

But what happens if a user removes a task while the a pomodoro is running? A great user experience would prevent the user from being able to do that, either by disabling the remove button when a pomodoro is active or by showing a prompt to the user. For now however, we're just gonna leave that as a bonus exercise or future improvement.

We're not displaying the pomodoros we've spent on a task quite yet, so let's not forget to do that. Back in the `TaskList.svelte` component we update our component markup to show that information:

```html
  <ul>
    {#each tasks as task}
      <li class:active={activeTask === task}>
        <button on:click={() => selectTask(task)}>&gt;</button>
        <input class="description" type="text" bind:value={task.description} bind:this={lastInput}>
        <input class="pomodoros" type="number" bind:value={task.expectedPomodoros}>
        <!-- NEW input -->
        <input class="pomodoros small" bind:value={task.actualPomodoros} disabled >
        <!-- END NEW -->
        <button on:click={() => removeTask(task)}>X</button>
      </li>
    {/each}
  </ul>
```

And our styles:

```css
.pomodoros.small { 
  max-width: 40px;
  text-align: center;
}
.active input[disabled] {
  opacity: 0.6;
}
```

And Tada! We finally have a working Pomodoro Technique app:

<img class="center shadow-small" src="https://www.barbarianmeetscoding.com/images/il-pomodoro-svelte-finally-integrated.gif" title="The pomodoro app finally integrated! Yiho!" alt="A pomodoro app with a timer and a series of tasks. The user clicks on a button and selects a task. When they select a task the pomodoro timer becomes active. The user clicks on start and the timer stars counting down.">

### An Alternative Approach With Slightly Less Coupling

While I was implementing the tasks and timer integration above I was somewhat unhappy with the idea that both the `TaskList` component and `PomodoroTimer` were modifying the same object `activeTask`. The more places within an application that have access and can modify the same data, the harder it becomes to reason about the state of the application and how it changes over time. This, in turn, means that a bug related to that piece of data could be introduced in many different places within an application. And it also was somewhat boilerplatey to have to pull the `activeTask` upwards to the parent `App` component to them pipe it down again to `PomodoroTimer`.

Here goes an alternative approach that sacrifies the independence of `PomodoroTimer` from `TaskList` but reduces the amount of code needed and reduces the coupling of data:

1. Include `PomodoroTimer` component inside the `TaskList` component
2. We have all the data we need so we can enable/disable the `PomodoroTimer` as needed
3. Instead of passing the `activeTask` into the `PomodoroTimer`, the timer communicates when a task has been complete through an event and the `TaskList` updates the `activeTask`.

```html
<PomodoroTimer disable={activeTask} on:completedPomodoro={() => activeTask.actualPomodoros++}/>
<ul>
  <!-- list of tasks remains unchanged -->
</ul>
```

## Sharing State Using a Store

Another way in which we can share state in Svelte are **stores**. Where sharing state through props is extremely coupled to the DOM tree and the structure of your application, sharing state through stores is completely DOM independent. Using Svelte stores you can share data between any component of your application, no matter where they are, with just a single import (that of the store).

> ### What is a Store?
>
> A store is an object that helps you share data between the components of a Svelte application. Stores are independent from the DOM tree and the structure of your application, so they are really useful when you need to share state between components that are far away from each other, or that should be decoupled. Stores are also reactive: whenever their value changes they notify their consumers of this change so that they can react to it. A component becomes a consumer of a store by subscribing to it via the `subscribe` method or `$` (you'll see some examples below).
>
> For more information about stores <a href="https://svelte.dev/docs#svelte_store">take a look at Svelte's Store documentation</a>

### The Active Task Store

Let's create a new store that will allow us to share the active task between the `TaskList` and the `PomodoroTimer` components. The `TaskList` component still has the complete list of tasks and will keep the responsibility of selecting the active task based on user input. This means that we can reuse much of the previous example. What's different? For one there won't be a `taskSelected` event and even more interestingly the `activeTask` will be a Svelte store.

Let' start by creating the store in its own file `tasksStore.js`:

```javascript
import { writable } from 'svelte/store';

export const activeTask = writable();
// The initial value of this store is undefined.
// You can provide an initial value by passing it as an argument
// to the writable function. For example:
// 
// const count = writable(0);
```

The `activeTask` is a **writable store** which in layman terms means that it is a store that components can use to write information that can then be shared between components. Aside from being a way to share information, stores are also reactive which means that they notify components when data has changed. Let's see how we can take advantage of these capabilities to communicate the `TaskList` and `PomodoroTimer` components.

> ### Writable Stores
> 
> <a href="https://svelte.dev/docs#writable">Writable stores</a> are stores that components can write to. In addition to `subscribe` they have the `set` and `update` methods that allow components to set a value in the store, or update the current value by applying a function.

The next step is to have `TaskList` import the `activeTask` store replacing the former `let activeTask` variable within the component.

```javascript
// import activeTask store
import {activeTask} from './tasksStore.js';

// remove old variable
// let activeTask
```

Since `activeTask` is now a store we can't just set its value as we did before. So instead of:

```javascript
  function selectTask(task) {
    activeTask = task;
  }
```

We need to use the `set` method of the store:

```javascript
  function selectTask(task) {
    activeTask.set(task);
  }
```

Likewise `activeTask` no longer refers to the activeTask itself but to the store that stores its value. In order to retrieve the current value of a task you use the `get` method. So intead of:

```javascript
function removeTask(task){
  if (activeTask === task){
    selectTask(undefined);
  }
  tasks = tasks.remove(task);
}
```

We write:

```javascript
// import get from svelte/store
import { get } from 'svelte/store';

// use it to retrieve the current value
// of the activeTask store and therefore
// the current task that is active
function removeTask(task){
  if (get(activeTask) === task){
    selectTask(undefined);
  }
  tasks = tasks.remove(task);
}
```

Using `set` and `get` can be quite wordy, so Svelte comes with an alternative syntax that lets you directly change and retrieve the value of a store by prepending it with a `$` sign when you're inside a component. 

Using that convenient syntax we can update the previous example with this one:

```javascript
// use it to retrieve the current value
// of the activeTask store and therefore
// the current task that is active.
function removeTask(task){
  if ($activeTask === task){
    selectTask(undefined);
  }
  tasks = tasks.remove(task);
}

// Use it to update the value of the activeTask.
function selectTask(task) {
  $activeTask = task;
}
```

Which looks very similar to the original implementation. Isn't that cool? We're using as store to manage our state but it pretty much looks just like setting and reading a normal JavaScript variable.

> ### get and set or $store? Which one to use?
>
> If you're inside a component then there's no reason to use get and set. Prefer using the shorter and less boilerplatey $store syntax.
>
> Outside of a component, when retrieving or updating the value of a store you'll need to use the get and set methods. Why? Because the $store syntax automatically subscribes and unsubscribes from a store by taking advantage of a component lifecycle events. You mount a component, you subscribe, you destroy a component, you unsubscribe. In the context of a vanilla JavaScript module however there's no concept of a lifecycle. Therefore the compiler wouldn't be able to know when it'd be a suitable time to unsubscribe from a store leading to memory leaks.

Whe can also use `$activeTask` within our component's template to check whether a given `li` belongs to the active task and highlight it:

```html
<ul>
  {#each tasks as task}
    <!-- update $activeTask here -->
    <li class:active={$activeTask === task}>
    <!-- END update -->
      <button on:click={() => selectTask(task)}>&gt;</button>
      <input class="description" type="text" bind:value={task.description} bind:this={lastInput}>
      <input class="pomodoros" type="number" bind:value={task.expectedPomodoros}>
      <input class="pomodoros small" bind:value={task.actualPomodoros} disabled >
      <button on:click={() => removeTask(task)}>X</button>
    </li>
  {/each}
</ul>
```

So now we can set the value of the `activeTask` whenever a user selects it within the `TaskList` component. The next step is to remove all references of `activeTask` from `App.svelte` and update our `PomodoroTimer` component to make use of the new store. 

We update the `completePomodoro` method using the same `$activeTask` syntax we learned earlier:

```javascript
import { activeTask } from './tasksStore.js';

function completePomodoro(){
  // Get the current active task and add a pomodoro
  $activeTask.actualPomodoros++; 
  completedPomodoros++;
  if (completedPomodoros === 4) {
    rest(LONG_BREAK_S);
    completedPomodoros = 0;
  } else {
    rest(SHORT_BREAK_S);
  }
}
```

And the template to enable and disable the timer whenever a task is active or not:

```html
<section>
  <time>
    {formatTime(pomodoroTime)}
  </time>
  <footer>
    <button class="primary" 
      on:click={startPomodoro} 
      disabled={currentState !== State.idle || !$activeTask}>start</button>
    <button 
      on:click={cancelPomodoro} 
      disabled={currentState !== State.inProgress || !$activeTask}>cancel</button>
  </footer>
</section>
```

If you take a look at the page right now (remember you can run the local dev environment with `npm run dev`) you'll be happy to see that everything is still working. Wihoo!

> ### What Type Of Stores Are Available in Svelte?
>
> In addition to <a href="https://svelte.dev/docs#writable">writable stores</a> Svelte has <a href="https://svelte.dev/docs#readable">readable</a> and <a href="https://svelte.dev/docs#derived">derived</a> stores. Readable stores are stores whose value can't be updated by a component. Derived stores are stores whose value is derived from other stores. Whenever these stores change, the value in the derived store is updated.
>
> If you want to <a href="https://svelte.dev/docs#svelte_store">learn more about Svelte stores take a look at the Svelte documentation</a>.

## Props vs Stores

Now that we've completed two different versions of our Pomodoro Technique app using both props and stores let's take a moment to reflect and compare both approaches:

### Props

**Svelte components define their interface with the outside world using props**. Using props allows parent components to communicate with children and *vice versa*. You can send data downwards from parent to child using props and upwards from children to parents using events.

#### Props Pros

* Sending data back and forth props is quite simple.
* Understanding the contract used to interact with a component is quite straightforward as it is defined by its props.
* Following the flow of data using props is as easy as seeing how data flows inside the component via props and comes out of the component via events.

#### Props Cons

* This type of state management creates a coupling between components and makes your application a little bit rigid: If a new requirement forces you to move a component to a different location in the page you may need to update the way you provide information to that component. 

#### When to Use Props

Because of all of the above it seems like props are a good solution for low level components that are completely isolated (a date picker, a type ahead, etc), or components that are near each other (in the DOM) and part of a closely related unit.

### Stores

Svelte stores are an extremely convenient way to share data between components in a loosely coupled way. Since you only need to import them to start accessing and changing data, they can be used to communicate any component anywhere within your application DOM tree.

#### Store Pros

* **They are more flexible than props and allow you to communicate components that are far away in your application DOM tree**. They don't force you to pass the information one step at a time through the DOM tree, one import and you can access and change your data.
* **They establish a loose coupling between components**. Using a store to communicate between components leads to flexible web applications where a requirement to change the layout of your application requires no changes in your data handling logic. That is, if you have two components that communicate using a store and all of the sudden you get the requirement to move one of them far across the page, there's no problem, you can just move it away and there's no additional code changes required. Compare that to a solution where both components communicate through props and you would be forced to change your state management strategy.

#### Store Cons

* The data interactions between components aren't as straightforward as when using props. Since the interactions no longer happen between components, but between a component and a store, it may be harder to reason about how actions on a component affect other components.

#### When to Use Stores

* Use stores when you need to communicate between components that are far away in your application DOM tree
* Use stores when you want to keep your options open and your components loosely coupled (e.g. if you expect that you may need to)

## Are There Any Other Way to Share State in Svelte?

In addition to props and stores, Svelte offers a middle ground solution: **[The Context API](https://svelte.dev/docs#setContext)**. The Context API allows you to communicate between components without passing lots of props or events deep inside the DOM tree. It consists on just two methods `setContext(key, value)` and `getContext(key)`. A parent component can use the `setContext(key, value)` method to save some data, that can then be retrieved by any child of that component using `getContext(key)`.

You can find an example of [how to use The Context API within Svelte Tutorials](https://svelte.dev/tutorial/context-api).

> ### Looking for the source code for the pomodoro app?
>
> Look no more! You can find it on <a href="https://github.com/Vintharas/il-pomodoro-in-svelte">GitHub</a> ready to be cloned and enjoyed, or on <a href="https://svelte.dev/repl/80e4829f3f0e42a7958c32f67a422d0a?version=3.18.1">the Svelte REPL</a> where you can tinker with it right away.
>

## More Reflections About Svelte

Working with Svelte continues to be very pleasant. In addition to my previous reflections ([1](https://www.barbarianmeetscoding.com/blog/2019/12/27/discovering-svelte-getting-started#some-reflections-so-far), [2](https://www.barbarianmeetscoding.com/blog/2019/12/29/discovering-svelte-adding-some-tasks-and-pomodoros#some-more-reflections-so-far), [3](https://www.barbarianmeetscoding.com/blog/2020/01/04/discovering-svelte-creating-a-pomodoro-timer#more-reflections)) I've found that:

* It is very easy to communicate components using props and events. The syntax is very straightfoward, lightweight and easy to remember.
* I really like that Svelte comes with a state management solution built-in and how easy it is to use stores change data or read it in a reactive fashion.

## Concluding

In this article we finally connected everything together and have a working pomodoro timer. Yihoo! We learned how you can use props and events to communicate between components that are near each other in the DOM tree, and how you can use stores to share data between components in a more loosely coupled fashion.

In upcoming parts of the series will dive into testing, async, animations and more. See you! Have a wonderful day!

[^1]: Check [this super old pomodoro technique app](https://www.barbarianmeetscoding.com/projects/ilpomodoro/) I wrote using Knockout.js back in the day I started doing web development.