DEV Community

Jonathan Gamble
Jonathan Gamble

Posted on

3

Sharing Custom Rune Classes with SvelteKit

Following my last article on Svelte 5 Runes, there are cases when you need to add custom functionality to a Rune, and share it. This method is pretty simple if you have been following this thread.

Implementation

You can share classes in Svelte, but safely sharing them in SvelteKit, requires a bit more code...

Create Your Class

class MyCounter {

    current = $state(0);

    constructor(value: number) {
        this.current = value;
    }

    increment() {
        this.current += 1;
    }

    decrement() {
        this.current -= 1;
    }
}
Enter fullscreen mode Exit fullscreen mode

This could be any class you want to share. This class happens to have a reactive $state() value, and shows an example of adding custom functionality like increment(). This method works best when you have complicated classes you want to share.

Create Your Custom Sharable Class

// add SSR protection with Context
import { getContext, hasContext, setContext } from "svelte";

export class _Counter {

    readonly #key: symbol;

    constructor(name: string) {
        this.#key = Symbol(name);
    }

    exists(): boolean {
        return hasContext(this.#key);
    }

    get(): MyCounter {
        return getContext(this.#key);
    }

    init(initialNumber: number): MyCounter {
        // initialize any class
        const _value = new MyCounter(initialNumber);
        return setContext(this.#key, _value);
    }
}
Enter fullscreen mode Exit fullscreen mode

Export the Class

export const useCustomCounter = new _Counter('counter');
Enter fullscreen mode Exit fullscreen mode

Usage

The usage would be the same as the Rune class from before.

// initialize value
const customCounter = useCustomCounter.init(1);
...
<h1>Hello from Parent Custom: {customCounter.current}</h1>
Enter fullscreen mode Exit fullscreen mode

And use it in children with your custom methods:

const customCounter = useCustomCounter.get();

<button type="button" onclick={() => customCounter.increment()}>
Increment Custom From Child
</button>
Enter fullscreen mode Exit fullscreen mode

Advanced Shared Class

If you know you're always going to be sharing a class, then you can make a generic SharedClass class to simplify things even more.

import { getContext, hasContext, setContext } from "svelte";

type Constructor<T, Args extends unknown[]> = new (...args: Args) => T;


export class SharedClass<T, Args extends unknown[]> {

    readonly #key: symbol;
    #class: Constructor<T, Args>;

    constructor(name: string, className: Constructor<T, Args>) {
        this.#key = Symbol(name);
        this.#class = className;
    }

    exists(): boolean {
        return hasContext(this.#key);
    }

    get(): T {
        return getContext(this.#key);
    }

    init(...args: Args): T {
        const _value = new this.#class(...args);
        return setContext(this.#key, _value);
    }
}
Enter fullscreen mode Exit fullscreen mode

And use it like so:

import { SharedClass } from "./shared-class.svelte";


class MyCounter {

    current = $state(0);

    constructor(value: number) {
        this.current = value;
    }

    increment() {
        this.current += 1;
    }

    decrement() {
        this.current -= 1;
    }
}

export const useCustomCounter = new SharedClass('counter', MyCounter);
Enter fullscreen mode Exit fullscreen mode

That's it!

Updated Code

J

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay