Search code examples
sveltesapper

How to pass data from a layout to a page in Sapper?


In Svelte you can pass props to the content in a slot.

<Component let:message="Hello!">
    <div>
        {message}
    </div>
</Component>

When Sapper uses a layout to render a route, the route contents are rendered in a slot too. The problem is that since Sapper takes control of this process it doesn't seem possible to pass a slot prop to a route.

This doesn't work:

// _layout.svelte
<slot message="Hello!"></slot>

So what is the appropriate way of passing data from a layout to a rendered route? For example segment.


Solution

  • Pass it down through context.

    One thing to be aware here is that a _layout component won't be recreated when the route change. And Svelte's context is not reactive. Conclusion: you need to wrap your data in a store.

    _layout.svelte

    <script>
      import { setContext } from 'svelte'
      import { writable } from 'svelte/store'
    
      export let segment;
    
      const segment$ = writable(segment)
    
      // this updates the store's value when `segment` changes
      // syntactic sugar for: segment$.set(segment)
      $: $segment$ = segment
    
      setContext('segment', segment$)
    </script>
    
    <slot />
    

    In some child page of this layout:

    <script>
      import { getContext } from 'svelte'
    
      const segment$ = getContext('segment')
    
      $: segment = $segment$
    
      $: console.log(segment)
    </script>