Copying Nuxt's useState in Qwik and Svelte

Nuxt has an amazing tool that allows you to easily share a signal called useState. Shared State Nuxt provides a perfect example: // composables/states.ts export const useColor = () => useState('color', () => 'pink') And you can can call the useColor hook from any component. // ---cut-start--- const useColor = () => useState('color', () => 'pink') // ---cut-end--- const color = useColor() // Same as useState('color') Current color: {{ color }} Let's duplicate this in other frameworks! SvelteKit Super easy, similar to my previous posts on the subject. import { getContext, hasContext, setContext } from "svelte"; export const useState = ( key: string, init?: () => T ) => { if (hasContext(key)) { return getContext(key); } if (!init) { throw new Error('You must initialize in the parent component!'); } const initialValue = init(); const state = $state({ value: initialValue }); setContext(key, state); return state; }; We can call it just the same: import { useState } from "./use-state.svelte"; export const useCounter = () => useState('counter', () => 1); Beautifantastic! Qwik A few more steps... import { createContextId, type Signal, useContext, useContextProvider, useSignal } from "@builder.io/qwik"; const useSharedContext = (name: string) => createContextId('io.builder.qwik.' + name); const useGetShared = (name: string) => useContext(useSharedContext(name), null); const useCreateShared = (name: string, content: T) => useContextProvider(useSharedContext(name), content); export const useState = ( key: string, init?: () => T, ) => { const shared = useGetShared(key); if (shared) { return shared; } if (!init) { throw new Error('You must initialize in the parent component!'); } const initialValue = init(); const state = useSignal(initialValue); useCreateShared(key, state); return state; }; And you call it the same way! import { useState } from "./use-state"; export const useCounter = () => useState('counter', () => 1); That's it! Now we can use the best part of Nuxt in SvelteKit and Qwik! Demo SvelteKit: Vercel Serverless Repo SvelteKit: GitHub Demo Qwik: Vercel Serverless Repo Qwik: GitHub I'm a nerd. Note: I didn't create this for Solid nor React because you can't conditionally run hooks. However, see my Universal Providers article for something similar.

Apr 1, 2025 - 04:58
 0
Copying Nuxt's useState in Qwik and Svelte

Nuxt has an amazing tool that allows you to easily share a signal called useState.

Shared State

Nuxt provides a perfect example:

// composables/states.ts

export const useColor = () => useState<string>('color', () => 'pink')

And you can can call the useColor hook from any component.

<script setup lang="ts">
// ---cut-start---
const useColor = () => useState<string>('color', () => 'pink')
// ---cut-end---
const color = useColor() // Same as useState('color')
</script>

<template>
  <p>Current color: {{ color }}</p>
</template>

Let's duplicate this in other frameworks!

SvelteKit

Super easy, similar to my previous posts on the subject.

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

export const useState = <T>(
    key: string,
    init?: () => T
) => {

    if (hasContext(key)) {
        return getContext<{ value: T }>(key);
    }

    if (!init) {
        throw new Error('You must initialize in the parent component!');
    }

    const initialValue = init();

    const state = $state<{ value: T }>({
        value: initialValue
    });

    setContext(key, state);
    return state;
};

We can call it just the same:

import { useState } from "./use-state.svelte";

export const useCounter = () => useState('counter', () => 1);

Beautifantastic!

Qwik

A few more steps...

import {
    createContextId,
    type Signal,
    useContext,
    useContextProvider,
    useSignal
} from "@builder.io/qwik";

const useSharedContext = <T>(name: string) =>
    createContextId<T>('io.builder.qwik.' + name);

const useGetShared = <T extends object>(name: string) =>
    useContext<T, null>(useSharedContext(name), null);

const useCreateShared = <T extends object>(name: string, content: T) =>
    useContextProvider<T>(useSharedContext(name), content);


export const useState = <T>(
    key: string,
    init?: () => T,
) => {

    const shared = useGetShared<Signal<T>>(key);
    if (shared) {
        return shared;
    }

    if (!init) {
        throw new Error('You must initialize in the parent component!');
    }

    const initialValue = init();
    const state = useSignal(initialValue);
    useCreateShared(key, state);
    return state;
};

And you call it the same way!

import { useState } from "./use-state";

export const useCounter = () => useState('counter', () => 1);

That's it!

Now we can use the best part of Nuxt in SvelteKit and Qwik!

Demo SvelteKit: Vercel Serverless
Repo SvelteKit: GitHub
Demo Qwik: Vercel Serverless
Repo Qwik: GitHub

I'm a nerd.

Note: I didn't create this for Solid nor React because you can't conditionally run hooks. However, see my Universal Providers article for something similar.