sveltesvelte-5

Bind to imported $state in svelte5 (error "constant_binding")


// states.svelte.js
export let name = $state("John"); // a state to be shared by multiple components
<!-- Component.svelte -->
<script>
  import { name } from "./states.svelte.js";
</script>

<p>Hello, my name is <input type="text" bind:value={name} /></p>

REPL

When migrating to svelte5, I try to replace a writable store with a $state, but get error Cannot bind to import (https://svelte.dev/e/constant_binding).

What's the correct way to do it?


Solution

  • I can only give the solution but not the why: when using runes for shared state they should be in an object:

    export const user = $state({
      name: 'John',
    });
    

    P.S. As @brunnerh showed in his answer, if an object name like userState doesn't make sense the convention is: const name = $state({ current: "John" })

    and:

    <script>
      import { userState } from "./states.svelte.js";
    </script>
    
    <p>Hello, my name is <input type="text" bind:value={user.name} /></p>
    

    Unfortunately the docs aren't clear that this is needed and why. I would also be interested to understand if it's a technical or philosophical imposition. I know that observables don't work well with primitive values as they're copied by value, so it could be technical.