Svelte without callbacks
Tags: svelte
Published: 2020-08-23 19:55:16

---
title: Svelte without callbacks
published: true
description: some head-scratchers and vagaries
tags: svelte
cover_image: http://blog.spencermounta.in/2019/wikipedias-in-trouble/assets/shirky-category.jpg
---

I've been doing front-end interviews this summer, which usually involve moving variables between React components. It's something I'm terrible at.

For years, jQuery applications were denounced for causing *'spaghetti code'* - where variables were scattered throughout different callbacks. It made reasoning about the application tricky.

React was welcomed and celebrated for making state/life-cycle explicit. It's really been helpful. ***Moving variables between components*** though, feels like it was always awkward, and seems to get more convoluted every year.

{% twitter 1131455129276694528 %}

This is what drew me to **Svelte** - you can change a variable *from-a-distance* in a spooky way. It seems to get around the need for all the spaghetti:

```html
<!-- Parent.svelte -->
<script>
  import Child from './child.svelte'
  let str = 'init'
  setTimeout(() => {
    str = 'changed'
  }, 2500)
</script>
<div>
  <Child {str} />
</div>

<!-- Child.svelte -->
<script>
  export let str = ''
</script>
<div>
  child: <b>{$str}</b>
</div>
```
Here, the child's HTML updates automatically. It's actually quite a remarkable thing. It feels like half the code is missing.

---

## There's no callbacks ...?
I'll admit, I do sometimes get stuck on control-flow issues in Svelte. There can be some puzzlers. I sometimes find myself throwing-around callbacks when I shouldn't.

Consider this example:
```html
<script>
  let value = 'foo'
</script>
<div>
  <input bind:value />
  magical variable: <b>{value}</b>
</div>
```
This variable is 'hot' - it's wired-up both-ways. If you look at the source, there's `getElementById's` and `addEventListener's` - the stuff you've normally been writing yourself.

---



## There's still no callbacks?
When a parent passes a variable to a child, the child will  automatically listen for changes. The parent will only listen to the child if you use `bind`:
```html
<!-- one-way (down) -->
<Child str={str} />
<!-- both-ways -->
<Child bind:str />
```
A grandchild can change a variable using nested binds - 

```
prop ➔ bind:prop ➔ bind:prop
```

A sibling can change a variable using two binds - 

```
prop ➔ [bind:prop, bind:prop]
```

In both cases, things are updated between all the components *automatically*, as though it were a spreadsheet.

---

Ok - this `bind` thing is crazy. It's automating a big-chunk of web-development. It's automating the chunk that sucks. I'm feeling it.

Arguably, *bind* also resolves a lot of those Redux job-interview questions that I mess up.

---

## But what about callbacks though?
I'm still a bit confused about this, admittedly. 

Svelte has a way that you can declare a variable with ***$:*** instead of ***let*** - and it enters the spooky dependency-graph - where it knows when variables change somehow.

I don't fully get it, but it seems really powerful:
```html
<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte'
  let str = 'init'
  // (fancy-part!)
  $: strLen = () => {
    return str.length
  }
</script>
<div>
  <Child bind:str />
  {strLen()}
</div>

<!-- Child.svelte -->
<script>
  export let str = ''
  setTimeout(() => {
    str = 'child-changed'
  }, 2000)
</script>
```
The function will re-fire after the child component changes the variable - and then the DOM will magically update, too

I mean, that's a callback. I just don't have to pass it around anymore. Using this **$:** thing, you can listen for changes, whenever you want to - from the top, the bottom, or in a side component. No sweat.

---

## Maybe there are callbacks
These three aspects - 
1. the ***'hot'*** props (going down)
2. the **'bind'** concept (going up)
3. the **$:** thing (anywhere)

They seem to be a complete interface. Maybe this is the interface we want to have for public libraries, and open-source components. I can't tell.

There seems to be no gospel about what a Svelte component interface ought to look like. A lot of libraries accept props, and callbacks for each prop that changes. This *'events-up'* callback style is cool with me too, I guess.

Oh - there is also [the Store concept](https://svelte.dev/tutorial/writable-stores). This is a observable *sub/pup* thing. I used stores a lot until I figured-out I didn't need them as much. They are more explicit and traditional about the variable updating.

Maybe Svelte components should accept writable stores as props? That would look something like this:
```html
<!-- Parent.svelte -->
<script>
  import { writable } from 'svelte/store'
  import Child from './Child.svelte'
  let str = writable('init')
  str.subscribe(wowChanged => {
    // is this a callback?
  })
</script>
<div>
  <Child {str} />
</div>

<!-- Child.svelte -->
<script>
  export let str
  setTimeout(() => {
    $str = 'child-changed' //change store
  }, 2000)
</script>
```
I guess that's cool too.

Oh, and there's [a Context concept](https://svelte.dev/tutorial/context-api) too, which avoids having to pass props down all-together. That seems cool.

Oh, and there's [a ton of people](https://www.reddit.com/r/sveltejs/comments/ekttox/how_to_add_redux_to_svelte/) adding redux back to svelte (for some reason). That seems cool.

The svelte developers are also building this *galaxy-brain* Multi-Page-App thing *[called Sapper](https://github.com/sveltejs/sapper)* which routes data around components presumably, too. Cool.

It's all cool. Svelte is a really fun, and flexible library to use. I hope this message-passing stuff becomes clearer, as more people jump in. I'd like to not have to think about it anymore.