Home > Web Front-end > JS Tutorial > Svelte Share state between components (for dummies)

Svelte Share state between components (for dummies)

Mary-Kate Olsen
Release: 2025-01-03 17:18:43
Original
435 people have browsed it

Svelte Share state between components (for dummies)

As soon as you see the new $state in Svelte 5, you might be tempted to do the following:

// sharedState.svelte.js
export const searchState = $state(""); // This won't work!
Copy after login
Copy after login
<!-- App.svelte -->
<script>
import { searchState } from './sharedState.svelte.js'

function handleClick(){
    // This won't work!
    searchState = "bicycles";
}
</script

<button onclick={handleClick}>Search for bicycles</button>
Copy after login
Copy after login

This won't work - and here is why:

You're encountering the most complicated part of Svelte 5. How reactivity works and how the compiler hides it from you.

When you export a single value like a number or string, there is no mechanism for Svelte to maintain reactivity because JavaScript doesn't offer a way to track that.

Huge thanks to Mat Simon who explained this to me in simple words ? Here is what I learned:

Use $state with objects and arrays, not strings!

You can't use a string directly, but all objects (and arrays) in $state get all their values proxied automatically by Svelte 5. Wrapping your string value into an object works:

// sharedState.svelte.js
// ❌ export const searchState = $state("");
export const searchState = $state({ text : "" });
Copy after login
Copy after login

This turned into an Svelte state object with a getter and a setter for .text. You can choose any property name you want, as well as multiple properties.

When you import this $state object, and then write .text =, you're using the Svelte setter to update the state:

// App.svelte

import { searchState } from './sharedState.svelte.js'

function handleClick(){
    // uses the automatically created setter
    searchState.text = "bicycles";
}

<button onclick={handleClick}>Search for bicycles</button>
Copy after login
Copy after login

Simple Demo (REPL)): Share $state between components (simple)

And Svelte is really clever about how to proxy these objects. That's why: myList.push('foo') works too for Arrays, because Svelte proxied the push method too.

// data.svelte.js
export const myList = $state([]);
Copy after login
Copy after login

Beware: Don't re-assign objects / arrays directly!

When you use an object (including arrays) they are also not states themselves! That's important to understand.

If you do this, you lost reactivity!

import { searchState } from './sharedState.svelte.js';
searchState = {text: "Hello world!"}; // don't do this!
Copy after login
Copy after login

There is no way for Svelte to handle this for you. Always use the automatic Svelte getter/setter via searchState.text = 'new value'.

Advanced: Use SvelteSet, SvelteMap, SvelteDate, etc.

Okay, objects and arrays are fine and handled by Svelte automatically - we got it.

But what about
Date, URL and more built-in objects of standard JavaScript? And if you're more experienced in JavaScript, you might know that there are some more advanced data types (standard built-in objects):

  • The Set object lets you store unique values of any type, whether primitive values or object references.

  • The Map object holds key-value pairs and remembers the original insertion order of the keys.

If you want to use these with reactive $state, you need to use their corresponding Svelte wrapper from svelte/reactivity

  • MediaQuery
  • SvelteDate
  • SvelteMap
  • SvelteSet
  • SvelteURL
  • SvelteURLSearchParams
// sharedState.svelte.js
export const searchState = $state(""); // This won't work!
Copy after login
Copy after login

The reason there is a separate SvelteSet and SvelteMap class (instead of just rewriting it automatically like they do with objects and arrays) is because they wanted to draw a line somewhere since they can't proxy every conceivable object. See https://github.com/sveltejs/svelte/issues/10263 for technical details.

Advanced: Use classes

There are multiple options to define your state objects, you can also use classes for custom methods: https://joyofcode.xyz/how-to-share-state-in-svelte-5#using-classes-for-reactive-state

Share state between components ($state & $derived)

So we know how to import (and update) states inside components and we know that we can use objects and array out of the box with $state:

<!-- App.svelte -->
<script>
import { searchState } from './sharedState.svelte.js'

function handleClick(){
    // This won't work!
    searchState = "bicycles";
}
</script

<button onclick={handleClick}>Search for bicycles</button>
Copy after login
Copy after login

We can even pass down the $state object as reference by a property with $props:

// sharedState.svelte.js
// ❌ export const searchState = $state("");
export const searchState = $state({ text : "" });
Copy after login
Copy after login
// App.svelte

import { searchState } from './sharedState.svelte.js'

function handleClick(){
    // uses the automatically created setter
    searchState.text = "bicycles";
}

<button onclick={handleClick}>Search for bicycles</button>
Copy after login
Copy after login

But how do you know that the state changed somewhere in your app when you're inside a component? That's what $derived and $derived.by are for:

// data.svelte.js
export const myList = $state([]);
Copy after login
Copy after login

Simple Demo (REPL)): Share $state between components (simple)

Usage with bind:value

As you might already know, there is no need to write handler functions for text inputs. You can just use bind:value={myStateObj} to update the state automatically:

import { searchState } from './sharedState.svelte.js';
searchState = {text: "Hello world!"}; // don't do this!
Copy after login
Copy after login

Usage with bind:group?

Multiple checkbox inputs can be handled with Svelte as well via bind-group={stateObj} - but there is still an open discussion about how to use it correctly with $state.

The good news: There are multiple ways to do this, see below.

Advanced demo: Search and filter product data

One way is to use the onchange event and update the state within the handler function.

Simple Demo (REPL): Search and filter with checkbox group components and v5 $state & $derived

Full SvelteKit example (WIP): https://github.com/mandrasch/austrian-web-dev-companies

I also started Reddit discussion to get more feedback:
What's the easiest way for search & filter checkboxes with Svelte v5 ($state)?

Happy to get your feedback there - or here as comment! ?

More resources

  • Different Ways To Share State In Svelte 5 - Joy of Code
  • Lets Build A Filtering System with Svelte 5 , Sveltekit 2, Tailwind, Upstash (2024) - Lawal Adebola
  • Svelte 5 - Global $state (convert stores to $state runes) - Svelte Mastery

Huge thanks to Mat Simon!

The above is the detailed content of Svelte Share state between components (for dummies). For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template