Managing state in Svelte
Tags: svelte, javascript, frontend
Published: 2020-02-26 21:40:15

---
title: Managing state in Svelte
published: true
description: Where should you put your state?
tags: svelte, JavaScript, frontend
---

A lot of what we do as developers is move state around.

We get state from the user, transform it, and pass it along to the server. Eventually we get some state back, transform it and then display it.

So, where is the right place to keep your state?

Svelte has multiple options depending on your needs, let's break them down:

# Props

When you want to send state downward through the component tree, you want a prop. It can be either a variable or expression:

```html
<Component prop1={someVar} prop2={a + b}/>
```

When any prop changes, the component is automatically re-rendered.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/347mfbrhj57peg7ie9e3.png)

# Events

Events bubble state upward. This allows a child components to signal a state change to a parent component.

To do this, create a dispatcher `dispatcher = createEventDispatcher()`, and then produce an event by calling `dispatch(eventName, eventData)`.

Here's an example: 

```html
<!-- Child.svelte -->
<script>
  import {createEventDispatcher} from 'svelte'

  // boilerplate required to produce events
  const dispatch = createEventDispatcher()

  // made up event handler
  function handleClick() {
    // fire event named 'message'
    dispatch('message', {data: ...})
  }
</script>
```

and the parent component looks like this:

```html
<!-- Parent.svelte -->
<script>
  // import the child component
  import Child from './Child'

  // event handler
  function handleMessage(data) {
    // do something interesting here :)
  }
</script>

<!-- wire up event handler for 'message' -->
<Child on:message={handleMessage}/>
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hw3184g6hw8sl1ic4s8s.png)

# Data Binding

It's very common for a parent and child component to sync state. Sure, it can be accomplished with just props and events, ie. the child publishes an event, the parent handles the event, and updates a prop.

It's so common, that Svelte provides a declarative shortcut called "data binding" 

Data binding syncs props in both directions, upwards & downwards, without event handling.

It works with any prop, simply add the `bind:` directive to the prop name.

Example:

```html
<!-- anytime var1 or var2 changes, <Component> will be re-rendered -->
<!-- anytime prop1 or prop2 changes inside <Component>, var1 & var2 are updated -->
<Component bind:prop1={var1} bind:prop2={var2}/>
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wstot8973v4yoesi9g8t.png)

# Context

Props, events and data binding are sufficient for most situations. 

But when you have a family of components that all share the same state, it can be tedious to pass the same props & events repeateadly. 

For this situation, Svelte gives us **Context**, which is way for a root component to share state with all its descendants.

The root component creates the state with `setContext('SOME_KEY', state)`, and then descendants can retrieve the state by calling `getContext('SOME_KEY')`.

Example:

```html
<!-- Root.svelte -->
<script>
  import {setContext} from 'svelte'

  // create context, MY_KEY is arbitrary
  setContext('MY_KEY', {value: 41})
</script>

<!-- notice, we don't need to pass props: -->
<Descendant/>
<Descendant/>
<Descendant/>
```

and, in the descendant component:

```html
<!-- Descendant.svelte -->
<script>
  import {getContext} from 'svelte'

  // read data from Context
  const {value} = getContext('MY_KEY')
</script>
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xl4iu0dmacimif2zjg17.png)

## Stores

Not all state belongs in the component tree. Sometimes there are visually disconnected components sharing the same state. 

Imagine an app with a logged in user. It would be tedious to pass the `user=` prop to every component. Many components would have to take the `user=` prop, just to pass it along because a grand-child or great-grand-child needed it.

This is where using a store makes sense, we can centralize the state of the user into a store. When a component needs user data, it can import it with `import {user} from './stores'`.

```javascript
// stores.js
// export a user store
export user = writable({name: "Tom Cook"})

// export functions to access or mutate user
export function signOut() {
  user.update(...)
}
```

And to use it:

```html
<!-- pages/Dashboard.svelte -->
<script>
  import {user} from '../stores'
</script>

<!-- notice the "$",  that tells svelte to subscribe to changes in the store -->
<h1>Welcome back {$user.name}!</h1>
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7rsp0vy0uybe076s6dh7.png)

# LocalStorage

To persist state locally between visits, `LocalStorage` is your friend. Svelte doesn't provide any specific feature for this, but you can easily roll your own by building a custom store.

Here is an example: https://gist.github.com/joshnuss/aa3539daf7ca412202b4c10d543bc077

# Summary

Svelte provides several ways to maintain state.

The most basic is keeping state in the visual tree.

Depending on the direction the state moves, you can use props, events, or data binding. When a family of components share state, use Context.

When state is used by many unrelated components, or to formalize access to data, use Stores. 


Happy coding!

✌️

If you want to learn more about Svelte, check out my upcoming [video course](https://svelte.video) ✨