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.
Top comments (0)