Rethinking Reactivity

Rich Harris

A talk about Svelte. By Rich Harris, creator of Svelte and graphics editor at the New York Times.

YouTube, Hacker News

Notes

Lanpar Technologies created a spreadsheet program which was the first example of forward referencing, AKA reactive programming. When a cell is updated, all the cells that depend on those cells are also updated.

Definition

The essence of cuntional reactive programming is to specify the dynamic behaviour of a value completely at the time of declaration.

Heinrich Apfelmus

React

React was the first library to use the Virtual DOM. Your code updates the Virtual DOM and then React updates the actual DOM based on that. It does a deep tree comparison between the old and new virtual DOM.

React doesn’t have any understanding of the valeus running through your app. It is not Reactive.

This is slow and to help React has methods such as shouldComponentUpdate, React.PureComponent, useMemo and useCallback, which break the abstraction.

Svelte

Rich wanted to use the declarative component framework, but without the overhead.

Frameworks are not tools for organising your code, they’re tools for organising your mind.

It turns your components into efficient low level to update the UI.

How do we tell if something has changed? In React (with classes), you call this.setState. In React (with hooks), you call setCount or whatever it’s called. In old Svelte we use this.set. The this is a problem, it introduces constraints to your API.

How do we tell the computer something changed? You look for the = operator?

Svelte 3

Reactivity is moved into the language.

<script>
let name = 'world';
let count = 0;

function handleClick() {
    count += 1;
}

function handleInput(event) {
    name = event.target.value;
}
</script>

<h1>Hello {name}</h1>
<input value={name} on:input={handleInput}>
<button on:click={handleClick}>
Clicks: {count}
</button>

The compiler adds invalidate calls to assignments.

We can use the bind directive, so that the input becomes:

<input bind:value={name} >

By putting JS in HTML (instead of HTML into JS) we can create different output formats - eg, server side rendering.

To use it:

import App from './App.svelte';

new App({
    target: document.querySelector('main'),
    // ...
});

Full Reactivity

We’re not yet reactive - we need state that is derived from other state. React doesn’t care about this because they rerun all the code (unless you use useMemo).

Inspiration from the Observable library, which is like Jupyter but it automatically runs the dependent cells. The post What is Reactive Programming (see end) creates the destiny operator which automatically updates a value if the value it is calculated from is updated.

There is some syntax that we could use (we don’t want anything too wacky because otherwise linters won’t work on our code).

let a = 10;
$: b = a + 1;

This is a labelled statement in JavaScript, which is rarely ever used. In Svelte this binds b to the value a + 1.

React’s Concurrent Mode

It’s painful when you’re typing something and because of the page updating you get input lag. This can be solved with debouncing, nothing updates until you stop typing. React’s concurrent mode updates while you’re typing, but if too much is going on the main thread (handling input) takes precedent over the background one (updating the UI).

In the example given Svetle works fine in single threaded mode. (The point of this part was to show that even with React’s attempts to speed up performance, single threaded performance matters.)

There’s more talk about Svelte having amazing performance (with examples such as Stone and Mustlab).

Accessibility

The Svelte compiler will warn you about accessibility issues. (I’m not quite sure why this is a big deal - it’s nothing new.)

Scoped Styles

Svelte files contain styles that are scoped to the file. The compiler adds a unique hash to the style. The compiler can also eliminate styles that aren’t used.

Transitions

Svelte contains transitions, using for example transition:fly={{y: 20}} . These are turned into CSS animations (off the main thread, better for performance and battery life).

There’s a fancy example of items being moved between lists and animating nicely.

Since Svelte is a compiler, you only pay for what you use.

Beyond Svelte

Sapper is a NextJS/Gatsby style framework - it contains automatic Server Side Rendering and Code-Splitting.

Svelte Native can be used to build iOS and Android applications.

Further Reading

What is Reactive Programming