Sharing Code Between Svelte Component Instances with Module Context
Tags: svelte, webdev, programming, javascript
Published: 2021-01-28 21:40:52

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


Svelte is an up and coming front end framework for developing front end web apps.

It’s simple to use and lets us create results fast.

In this article, we’ll look at how to share variables between component instances with module context.

### Module Context

Svelte components can contain code that is shared between multiple component instances.

To do this, we can declare the script block with `context='module'` . The code inside it will run once, when the module first evaluates, rather than when a component is instantiated.

For instance, we can use it to create multiple audio elements that can only have one audio element play at a time by stopping the ones that aren’t being played as follows:

`App.svelte` :

```
<script>
  import AudioPlayer from "./AudioPlayer.svelte";
</script>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3"
/>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_1MG.mp3"
/>

<AudioPlayer
  src="http://www.hochmuth.com/mp3/Haydn_Cello_Concerto_D-1.mp3"
/>
```

`AudioPlayer.svelts` :

```
<script context="module">
  let current;
</script>

<script>
  export let src;

  let audio;
  let paused = true;

  const stopOthers = () =>{
    if (current && current !== audio) current.pause();
    current = audio;
  }
</script>

<article>
  <audio
    bind:this={audio}
    bind:paused
    on:play={stopOthers}
    controls
    {src}
  ></audio>
</article>
```

In the code above, we have the `AudioPlayer` component which has the code that’s shared between all instances in:

```
<script context="module">
  let current;
</script>
```

This lets us call `pause` on any instance of the audio element that isn’t the one that’s being played as we did in the `stopOthers` function. `stopOthers` is run when we click play on an audio element.

Then we included the `AudioPlayer` instances in the `App.svelte` component.

Therefore, when we click play on one of the audio elements, we pause the other ones.

### Exports

Anything that’s exported from a `context='module'` script block becomes an export of the module itself. For instance, we can create a button to stop all the audio elements in `AudioPlayer` that is currently playing as follows:

`App.svelte` :

```
<script>
  import AudioPlayer, { stopAll } from "./AudioPlayer.svelte";
</script>

<button on:click={stopAll}>Stop All</button>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3"
/>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_1MG.mp3"
/>

<AudioPlayer
  src="http://www.hochmuth.com/mp3/Haydn_Cello_Concerto_D-1.mp3"
/>
```

`AudioPlayer.svelte` :

```
<script context="module">
  let elements = new Set();

  export const stopAll = () => {
    elements.forEach(element => {
      element.pause();
    });
  };
</script>

<script>
  import { onMount } from 'svelte';
  export let src;
  let audio;

  onMount(() => {
    elements.add(audio);
    return () => elements.delete(audio);
  });
</script>

<article>
  <audio
    bind:this={audio}
    controls
    {src}
  ></audio>
</article>
```

In the code above, we add all the audio element instances to the `elements` set which we created in the `contex='module'` block as each `AudioPlayer` component is mounted.

Then we export the `stopAll` function, which has all the audio element instances from `elements` , and we call `pause` on all of them by looping through them and calling `pause` .

In `App.svelte` , we import the `stopAll` function from `AudioPlayer` and then call it when we click the Stop All button.

Then when we click play on one or more audio elements, they’ll all be paused when we click the Stop All button.

Note that we can’t have a default export because the component is the default export.

### Conclusion

We can use the module context script block to add script blocks that are shared between all instances of a component.

If we export functions inside module context script blocks, we can import the function and then call it.