Svelte journey | Context API, Special Elements, Modularity, Debug
Denys Sych
Posted on December 30, 2023
Welcome,
today on our plate are as many tasty topics as before in previous articles. We'll cover contexts that allow us to set up component communication in a way that differs from props and event dispatching, special Svelte elements that enable us to handle some cases that are not achievable with other tooling. Then, we'll move to modules in Svelte and wrap up with a couple of words about debugging.
Context
Similar to React’s Context concept. In a nutshell: can be used for component communication omitting props & events.
-
setContext
andgetContext
must be called during component initialization; - Context can include anything, including stores, functions, objects, etc.
<!-- Parent.svelte -->
<script>
import { setContext } from 'svelte';
setContext('canvas', {
addItem
});
function addItem(fn) {...}
</script>
// ...
<!-- Child.svelte -->
<script>
import { getContext } from 'svelte';
// ...
getContext('canvas').addItem(draw);
function draw(ctx) {...};
</script>
// ...
Example with a store:
setContext('my-context', {
count: writable(0)
});
const { count } = getContext('my-context')
$: console.log({ count: $count });
Special elements — built-in Svelte utility elements
svelte:self
<svelte:self {...props} />
— render component inside itself recursively (e.g., useful for a folder tree view).
svelte:component
<svelte:component this={selected.component}/>
— you can render a component that you store in some variable.
- When a property changes, the component is destroyed and recreated;
- Can be falsy value → in that case, no error is thrown & nothing is rendered.
Similar behavior in React:
import { FancyButton, UglyBanner } from 'my-pocket';
function Container() {
const { isBelovedClient } = useClientService();
const Component = isBelovedClient ? FancyButton : UglyBanner;
return <Component />;
}
In Svelte:
<script>
import FancyButton from './FancyButton.svelte';
import UglyBanner from './GreeUglyBannernThing.svelte';
import isBelovedClient from './client-service.js';
const targetComponent = isBelovedClient ? FancyButton : UglyBanner;
</script>
<svelte:component this={targetComponent}/>
svelte:element
Pretty much the same as <svelte:component />
but for basic HTML elements, not Svelte components.
- The only supported binding is
bind:this
(nobind:value
. Why: Svelte binds at build time); - Runtime error in case some children inside a void element (like
<br />
).
<svelte:element this={'div'}>
I'm a div
</svelte:element>
svelte:window
Interact with the window
object. Supports bindings and handlers assignment.
<svelte:window on:keydown={handleKeydown} bind:scrollY={y} />
Bind props (All except scrollX
and scrollY
are readonly):
-
innerWidth
; -
innerHeight
; -
outerWidth
; -
outerHeight
; -
scrollX
; -
scrollY
; -
online
— an alias forwindow.navigator.onLine
.
svelte:body
svelte:body
is like svelte:window
but for document.body
. E.g., on:mouseenter
and on:mouseleave
are not available in window
but in document.body
.
svelte:document
Allows you to listen for events that fire on document
. E.g., selectionchange
.
svelte:head
Allows you to insert elements inside the <head>
of the document.
<!-- App.svelte -->
<svelte:head>
<link rel="stylesheet" href="/stylesheets/{selected}.css" />
</svelte:head>
- In SSR mode contents of
<svelte:head>
are returned separately from the rest of HTML.
svelte:options
To configure compiler options. There are a lot, a full list is better to check in the documentation.
- Can be configured per component.
Example, telling the compiler that the component works with immutable data (by default Svelte works with mutable):
<svelte:options immutable />
<script>...</script>
...
svelte:fragment
Similar to React.Fragment. When you need to group several elements/components without a container DOM element.
Can be used with slot
<svelte:fragment slot="game">
<button />
<input />
</svelte:fragment>
Modularity
Run module code once
<script context="module">
— makes code run once, when the module first evaluates, not when the component initializes. You can have several <script />
tags per file, so it is possible to have default behavior as well:
<script context="module"> //
let current;
</script>
<script>
export let title;
//...
</script>
It gives you the ability to keep persistent state, have singletons, etc.
Imports & Exports
Anything exported from a context="module"
script block becomes an export from the module itself.
No default export for the module, because the component itself is the default export.
// Player.svelte -----------------------------------------------------
<script context="module">
let current;
export const stopAll = () => current?.pause();
</script>
// ...
// App.svelte --------------------------------------------------------
<script>
import AudioPlayer, { stopAll } from './AudioPlayer.svelte';
</script>
// ...
You may remember also that if you do export from a regular <script />
it is also possible to access exported parts together with bind:this
mechanism (bind:this section). The difference is that with context="module"
you can do a particular import
, and this code is not about a component instance but about a module, as it was mentioned before.
Debug
Old plain console.log(...)
in the markup section or special {@debug ...}
tag with a comma-separated list of values you want to inspect.
<script>
let name = 'Ada';
</script>
<input bind:value={user.firstname} />
{@debug user}
<h1>Hello {user.firstname}!</h1>
@debug
with devtools opened also stops execution, shows a stack trace and other debug regular things.
I'm happy to share with you that this article is a finishing point of our Svelte’s overview! This article wraps up the part about Svelte as a UI library / component framework for building robust interfaces.
But it is not the finish line in our journey; it is just another turn over! In the next article, we’ll start to explore SvelteKit framework — framework / metaframework, that provides surrounding tooling for building full-steam applications.
See you in the next articles,
take care, go Svelte!
Resources
- Svelte Tutorial | Context API, Special Elements, Module context, Miscellaneous
Posted on December 30, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
January 5, 2024