Learning Svelte 5 | state

Originally published on 17 January, 2021 by Jacob Stordahl

Today we're returning to Svelte to learn about state. Understanding state will make your components incredibly dynamic. First off I think it's helpful to define what state is if you're new to component based web development. State is best explained by an example we're all familiar with; a form that validates entries.

The 'state' of this form depends on the data entered. If the user inputs data in the wrong format, the form will try to validate the data, the validation will fail, and the form will then update it's state to show the user that they have entered their data incorrectly. This usually consists of outlining the form field in red, and displaying an error message below it. This form field will likely have many different possible states it can be in at any given moment, and it's our job to keep track of how the state changes as a user interacts with our component.

The React docs have an excellent explanation of state, if you understand props; "State is similar to props, but it is private and fully controlled by the component". In other Javascript frameworks, like React, an API (be it internal or external) is needed to manage your application state. However, in Svelte, all global variables inside of a component represent that component's state. Let's take a look at the counter example from the docs...

<script>
  let count = 0;

  function handleClick () {
    // calling this function will trigger an
    // update if the markup references `count`
    count = count + 1;
  }
</script>

<h1>{count}</h1>
<button on:click={handleClick}>Increment Count</button>

With this small amount of code, we now have a button that will automatically update our UI instantly, & this code is very readable and understandable. Remember that Svelte is based around a "powerful system of reactivity" that keeps the DOM in sync with our application. The most prominent feature of this reactivity is that: when the value of a variable changes in the template, the template will re-render. Let's see this in action be looking back at the last example. Our state is managed in such a way that it's simple to create very complex user interaction. Let's add some additional functionality to our above example...

<script>
  let count = 0;

  //we'll also convert our functions to arrow functions for brevity
  const increment = () => { count = count + 1 };
  const decrement = () => { count = count - 1 };
  const double = () => { count = count * 2 };
  const split = () => { count = count / 2 };
</script>

<h1>{count}</h1>
<button on:click={increment}>Increment Count</button>
<button on:click={decrement}>Decrement Count</button>
<button on:click={double}>Double Count</button>
<button on:click={split}>Split Count</button>

If you'd like to view this example, check out the REPL

With only 14 lines of code, our user is able to transform our component state in 4 different ways. That's awesome! Because our Svelte templates re-render when any variable referenced in the template changes all we need to do is change the value of a state variable through a simple assignment. To illustrate the relationship between state variables and our template, let's write an over-engineered hello world...

<script>
  //FILL AN ARRAY WITH HELLOS
  const helloArr = [
    'bonjour',
    'holla',
    '你好',
    'hallo',
    'Здравствуйте',
    'ciao',
    'नमस्कार',
    'olà',
    'مرحبا'
  ]

  //INITIALIZE STATE VARIABLE 'HELLO' WITH DEFAULT VALUE
  let hello = 'hello'

  let index = 0;

  //DEFINE OUR FUNCTION
  const changeHello = () => {
     hello = helloArr[index];
      if (index === helloArr.length) {
          index = 0;
          hello = 'hello';
      } else {
          index++;
      }
  }

  //CREATE OUR INTERVAL
  const interval = setInterval(changeHello, 1500);
</script>

<div>
    <h1>{ hello } world!</h1>
</div>

In this example, we're creating one piece of state in our component, called hello. We also define a top level variable called index to keep track of our location in the helloArr. We then define our function changeHello which simply sets our state variable hello to the item in helloArr with the same location as index. Our function then just checks if index is equal to the length of helloArr, and if so we reset index & our state variable hello. Lastly, we are creating a variable interval which makes use of the setInterval method to create a regular repeating action. setInterval takes two arguments; the function you'd like to run in your interval, and the number of milliseconds between each function call. All we have to do now is place our hello state variable inside of our template and voilà! If you'd like to see this example, check it out on the Svelte REPL.

Compared to other Javascript frameworks, Svelte's approach to state is, in my opinion, incredibly approachable, intuitive & allows for easily maintainable components.

Next time, we'll return to Svelte and look at the component lifecycle

© 2021 Jacob Stordahl | built with Steel