Svelte: Reactive Cheat Sheet

Reactive Expressions:

<script>
  let num = 0
  $: squared = num * num
  $: cubed = squared * num
</script>

<button on:click={() => num = num + 1}>
  Increment: {num}
</button>

<p>{squared}</p>
<p>{cubed}</p>

Reactive Statement:

<script>
  $: if (count >= 10) {
    alert('count is dangerously high!')
    count = 9
  }

  let foo, bar, baz

  $: quux = foo + bar
  $: console.log(quux)

  $: {
    // block expression
  }

  $: if (quux > 10) {
    // actually any ->
  } else {
    // js expression
  }

  $: for (let i = 0; i < baz; i++) {
    // any js expression
  }

  // function declaration too
  $: grunt = arg => quux / arg * baz

  $: { // this would also work
    if (quux < 10) break $
    baz++
  }

  $: (async () => { // and even this
    bar = await Promise.resolve(foo%2)
  })()
</script>

Svelte: Transitions Cheat Sheet

<script>
  import { fade } from "svelte/transition";
  export let condition;
</script>

{#if condition}
  <div transition:fade={{ delay: 250, duration: 300 }}>
    fades in  and out
  </div>
{/if}

// Other transitions
[Blur, Scale, Fly, Draw, Slide]

Svelte: Animations Cheat Sheet

<script>
  import { flip } from "svelte/animate";
  import { quintOut } from "svelte/easing";
  let list = [1, 2, 3];
</script>

{#each list as n (n)}
  <div animate:flip={{ 
    delay: 250, 
    duration: 250, 
    easing: quintOut
  }}>
    {n}
  </div>
{/each}

Svelte: Slot Cheat Sheet

Using Slot:

<!-- Widget.svelte -->
<div>
  <slot>Default content</slot>
</div>

<!-- App.svelte -->
<Widget />
<Widget>
  <p>I   changed the default content</p>
</Widget>

Multiple Slot:

<!-- Widget.svelte -->
<div>
  <slot name="header">
    No header was provided
  </slot>

  <slot>
    <p>Some content between header and footer</p>
  </slot>

  <slot name="footer" />
</div>

<!-- App.svelte -->
<Widget>
  <h1 slot="header">Hello</h1>
  <p slot="footer">
    Copyright (c) 2020 Svelte Brazil
  </p>
</Widget>

<!-- FancyList.svelte -->
<ul>
{#each items as item}
  <li class="fancy">
    <slot name="item" {item} />
  </li>
{/each}
</ul>

<!-- App.svelte -->
<FancyList {items}>
  <div slot="item" let:item>
    {item.text}
  </div>
</FancyList>

Svelte: Forwarding Events Cheat Sheet

// Widget.svelte
<script>
  import { createEventDispatcher } from "svelte";
  const dispatch = createEventDispatcher();
</script>
<button on:click={() => dispatch('message', { text: 'Hello!' })} />
<button on:click>Press me</button>

// App.svelte
<script>
import Widget from '.Widget.svelte'
</script>

<Widget 
  on:click={() => alert('I was clicked')} 
  on:message={e => alert(e.detail.text)}>

Svelte: Handle Events Cheat Sheet

<button on:click={handleClick}>
  Press me
</button>

<button on:click={() => console.log('I was pressed')}>
  Press me
</button>

<button on:click|once={handleClick}>
  Press me
</button>

<button on:submit|preventDefault={handleClick}>
  Press me
</button>

Svelte: Render HTML Cheat Sheet

<scrit>
  const myHtml = '<span><strong>My text:</strong> text</span>'
</scrit>

{@html '<div>Content</div>'}

{@html myHtml}

Svelte: Animation Cheat Sheet

<script>
  import { flip } from "svelte/animate";
  import { quintOut } from "svelte/easing";
  let list = [1, 2, 3];
</script>

{#each list as n (n)}
  <div animate:flip={{ 
    delay: 250, 
    duration: 250, 
    easing: quintOut
  }}>
    {n}
  </div>
{/each}

Svelte: Motion Cheat Sheet

Tweened

<script>
  import { tweened } from 'svelte/motion';
  import { cubicOut } from 'svelte/easing';

  const progress = tweened(0, {
      duration: 400,
      easing: cubicOut
  });
</script>

<progress value={$progress}></progress>

<button on:click="{() => progress.set(0)}">0%</button>

Spring

<script>
  import { spring } from 'svelte/motion';

  let coords = spring({ x: 50, y: 50 }, {
      stiffness: 0.1,
      damping: 0.25
  });
  let size = spring(10);
</script>

Svelte: Store Cheat Sheet

A store is simply an object with a subscribe method that allows interested parties to be notified whenever the store value changes:

<script>
  let countValue;
  const unsubscribe = count.subscribe(value => {
    count_value = value;
  });
  onDestroy(unsubscribe);
</script>

<h1>The count is {count_value}</h1>

Update the stored value:

<script>
  function increment() {
    count.update(n => n + 1)
  }
</script>

Set a value:

<script>
  function reset() {
    count.set(0);
  }
</script>

Usage

Use auto-subscription to get rid of subscribe and onDestroy methods:

<script>
  import { storeValue } from './AnotherComponent'
  // ...other imports come after
</script>

<h1>The count is {$storeValue}</h1>

Readable store

<script>
  export const time = readable(new Date(), function start(set) {
    // Implementation
    set()

    return function stop() {
      // Implementation
    }
  })
</script>

Writable store

<script>
  import { writable } from 'svelte/store';

  const count = writable(0, () => {
    console.log('got a subscriber');
    return () => console.log('no more subscribers');
  });
</script>

Derived store

…from another store.

<script>
  import { derived } from 'svelte/store';

  const delayed = derived(time, ($a, set) => {
    setTimeout(() => set($a), 1000);
  }, 'one moment...');

  // or (read-only derived):

  const elapsed = derived(time, $time =>
    Math.round(($time - start) / 1000)
  );

</script>

Custom store

// store.js

import { writable } from 'svelte/store';
function createCount() {
  const { subscribe, set, update } = writable(0);

  return {
    subscribe,
    increment: () => update(n => n + 1),
    decrement: () => update(n => n - 1),
    reset: () => set(0)
  };
}
export const count = createCount();

In the component:

<script>
  import { count } from './store.js';
</script>

<h1>The count is {$count}</h1>

<button on:click={count.increment}>+</button>
<button on:click={count.decrement}>-</button>
<button on:click={count.reset}>reset</button>

Svelte: Conditional Render Cheat Sheet

{#if condition}
  <p>Condition is true</p>

  <p>OtherCondition is true</p>

  <p>Any Condition is true</p>
{/if}

// Re render
{#key value}
	<div transition:fade>{value}</div>
{/key}

Svelte: Events Cheat Sheet

You can bind functions/ events to your tags:

<script>
  let count = 0;

  function handleClick() {
    count += 1;
  }
</script>

<button on:click={handleClick}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

You can use all javascript event (click, mousemove, …). You can also modify event by piping modifiers to it: <button on:click|once={handleClick}> You can chain them by adding pipes.

Event dispatcher

You can create an event dispatcher inside a component. It must be called when the component is first instantiated.

<script>
  import { createEventDispatcher } from 'svelte';

  const dispatch = createEventDispatcher();

  function sayHello() {
    dispatch('message', {
      text: 'Hello!'
    });
  }
</script>

On the other side:

<script>
  import Inner from './Inner.svelte';

  function handleMessage(event) {
    alert(event.detail.text);
  }
</script>

<Inner on:message={handleMessage}/> // on:eventname

Event forwarding

You can handle events from any other component by calling them with their own event:

// Outer.svelte
<script>
  import Inner from './Inner.svelte';
</script>

<Inner on:message/>

Here we can intercept the event message from Inner. Then, when called, we can define how the component reacts:

<Outer on:message={handleMessage}/>

Svelte: Lifecycle Cheat Sheet

Lifecycle functions:

  • onMount
<script>
import onMount from 'svelte'

onMount(() => {
  console.log('Mounting')
  return () => (consolo.log('going out'))
})
</script>
  • beforeUpdate
  • afterUpdate
  • onDestroy

Svelte: Await Template Cheat Sheet

{#await promise}
  <p>waiting for the promise to resolve...</p>

  <p>The value is {value}</p>

  <p>Something went wrong: {error.message}</p>
{/await}

Svelte: Logic Cheat Sheet

Conditions:

{#if user.loggedIn}
  <button on:click={toggle}>
    Log out
  </button>
{/if}

{#if !user.loggedIn}
  <button on:click={toggle}>
    Log in
  </button>
{/if}

Conditional Render:

{#if condition}
  <p>Condition is true</p>

  <p>OtherCondition is true</p>

  <p>Any Condition is true</p>
{/if}

// Re render
{#key value}
	<div transition:fade>{value}</div>
{/key}

Loops:

{#each cats as cat, i}
  <li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
    {i}: {cat.name}
  </a></li>
{/each}

Tip: You can also de-structure as: {#each cats as { id, name }} and then use {name} instead of {cat.name}

When a value isn’t exported but is computed by a prop, you can go into problems when updating values since it’s a copy and not a reference. Thus, be sure to identify the right object when updating its value(s):

{#each cats as cat, i (cat)} // Notice the (cat)
  <li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
    {i}: {cat.name}
  </a></li>
{/each}

Promises:

{#await promise}
  <p>Loading...</p>
{:then result}
  <p>It returns {result}</p>
{:catch error}
  <p>An error occurred: {error.message}</p>
{/await}

Tip: You can also skip loading step by using: {#await promise then result}

Svelte: Use action Cheat Sheet

<script>
  function myFunction(node) {
    // the node has been mounted in the DOM
    return {
      destroy() {
        // the node has been removed from the DOM
      }
    };
  }
</script>

<div use:myFunction></div>

Svelte: Bind Cheat Sheet

Simple Bind:

//MyLink.svelte
<script>
    export let href = ''
    export let title = ''
    export let color = ''
</script>

<a href={href} style={`color: ${color}`} >
  {title}
</a>

// Shorthand
<a {href} style={`color: ${color}`} >
  {title}
</a>

<script>
  import MyLink from "./components/MyLink";
  let link = {
    href: "http://www.mysite.com",
    title: "My Site",
    color: "#ff3300"
  };
</script>

<MyLink {...link} />

Two Way Bind:

<MyInput bind:value={value} />

// Shorthand
<MyInput bind:value />

<select multiple bind:value={fillings}>
  <option value="Rice">Rice</option>
  <option value="Beans">Beans</option>
  <option value="Cheese">Cheese</option>
</select>

<input 
  type="radio" 
  bind:group={tortilla} 
  value="Plain" />
<input
  type="radio" 
  bind:group={tortilla} 
  value="Whole wheat" />

<input 
  type="checkbox" 
  bind:group={fillings} 
  value="Rice" />
<input 
  type="checkbox" 
  bind:group={fillings} 
  value="Beans" />

// Element Binding
<script>
  let myDiv
</script>

<button on:click={() => myDiv.innerText = 'My text'}>
  Click
</button>

<div bind:this={myDiv}/>

Svelte: Props Cheat Sheet

There’s an easy way to pass props to a child component. Just export it !

// Nested.svelte
<script>
  export let answer = 42
</script>
<p>The answer is {answer}</p>

// App.svelte
<script>
  import Nested from './Nested.svelte'
</script>

<Nested/> // Will display: The answer is 42

Tip: You can also use <Nested answer={42}/> to set a default value to a prop that hasn’t been initialized into it’s own component.

When passing multiple props typically as an object of properties, you can spread them to a component instead of specifying each one with ...:

<script>
  import Info from './Info.svelte';

  const pkg = {
    name: 'svelte',
    version: 3,
    speed: 'blazing',
    website: 'https://svelte.dev'
  };
</script>

<Info name={pkg.name} version={pkg.version} speed={pkg.speed} website={pkg.website}/>
<Info {...pkg}/>

Assuming we have exported nameversion, and so on in the Info component.

Svelte: Reactivity Cheat Sheet

Variables

Sometimes a variable is result from a computation, you’ll have to use a reactive declaration:

let count = 0
$: doubled = count * 2

Expressions

<script>
  let num = 0
  $: squared = num * num
  $: cubed = squared * num
</script>

<button on:click={() => num = num + 1}>
  Increment: {num}
</button>

<p>{squared}</p>
<p>{cubed}</p>

Statement

<script>
  $: if (count >= 10) {
    alert('count is dangerously high!')
    count = 9
  }

  let foo, bar, baz

  $: quux = foo + bar
  $: console.log(quux)

  $: {
    // block expression
  }

  $: if (quux > 10) {
    // actually any ->
  } else {
    // js expression
  }

  $: for (let i = 0; i < baz; i++) {
    // any js expression
  }

  // function declaration too
  $: grunt = arg => quux / arg * baz

  $: { // this would also work
    if (quux < 10) break $
    baz++
  }

  $: (async () => { // and even this
    bar = await Promise.resolve(foo%2)
  })()
</script>

Updating objects

Because Svelte’s reactivity is triggered by assignments following code won’t do anything when called:

function addNumber() {
  numbers.push(numbers.length + 1);
}

Unless you add it this assignment:

function addNumber() {
  numbers.push(numbers.length + 1);
  numbers = numbers;
}

Svelte: Expressions Cheat Sheet

<script>
  let isShowing = true
  let cat = 'cat'
  let user = {name: 'John Wick'}
  let email = '[email protected]'
</script>

<p>2 + 2 = {2 + 2}</p>
   
<p on:click={() => isShowing = !isShowing}>
  {isShowing 
    ? 'NOW YOU SEE ME 👀' 
    : 'NOW YOU DON`T SEE ME 🙈'}
</p>

<p>My e-mail is {email}</p>
<p>{user.name}</p>
<p>{cat + `s`}</p>
<p>{`name ${user.name}`}</p>

Svelte: Component Cheat Sheet

<!-- Widget.svelte -->
<script>
  export let textValue
</script>

<div class="container">
  {textValue}
</div>

<style>
.container {
  color: blue;
}
</style>

<!-- App.svelte -->
<script>
  import Widget from './Widget.svelte'
  const title = 'App'
</script>

<header>{title}</header>

<Widget textValue="I'm a svelte component" />

Svelte: Variables

Define variables in your <script> tag and then use it with brackets:

<script>
  let foo = "bar"
</script>

<p class={bar}>Some text</p>

Tip: It also works inside double-quotes: <p class="primary-{bar}">Some text</p>

Moreover, when var = attribute, (src={src}) you can use it this way: {src}.

Svelte: Imports

Include a component inside another one by importing it:

<script>
  import Nested from './Nested.svelte'
</script>

<Nested/>

Svelte: Structure

Your component use few tags to be operating:

  • <script>
  • <style>

<script> will describe how to animate the component. <style> how to render it.