Blog Posts

Svelte 5 State Management

Learn how to manage state using Svelte's context and a class-based approach.

November 15, 2025
3 Minutes Read

The best way to handle state in Svelte 5 is with a class-based approach using Svelte's setContext and getContext. This allows us to access shared app state anywhere in the application without prop drilling.

Creating the file

Create a svelte.ts or svelte.js file. For this example, we will create the file src/lib/hooks/app.svelte.ts to manage our app state as shown below.

src/lib/hooks/app.svelte.ts
import { MediaQuery } from "svelte/reactivity";
import { setContext, getContext } from "svelte";

/** App state class-based management */
class UseApp {
	isDarkMode = $state(false);
	isMobile = $derived(new MediaQuery("max-width: 700px").current);

	// Set default data
	constructor(props: { [key: string]: any }) {
		// Merge props into this instance
		Object.assign(this, props);
		// Add or remove dark class on body whenever `isDarkMode` changes
		$effect(() => {
			document.body.classList.toggle("dark", this.isDarkMode);
		});
	}

	/** Toggle isDarkMode */
	darkModeToggle = () => (this.isDarkMode = !this.isDarkMode);
}

/** Hook props (isDarkMode can be set when initializing the hook) */
export type UseAppProps = Pick<InstanceType<typeof UseApp>, "isDarkMode">;

/** Set app state */
export const setApp = (props: UseAppProps) => setContext("appState", new UseApp(props));

/** Use app state */
export const useApp = () => getContext<ReturnType<typeof setApp>>("appState");

Initializing the app state

After creating the Svelte app hook, you need to initialize it inside your app layout, such as src/routes/+layout.svelte or src/App.svelte for Vite.js projects.

src/routes/+layout.svelte
<script lang="ts">
	import { setApp } from "$lib/hooks/app.svelte.js";
	// Set app hook
	const { children } = $props();
	const app = setApp({ isDarkMode: false });
	// We can use it right away
	app.isDarkMode; // false
</script>

{@render children()}

Using the app state

Now we can use our app state inside any component without passing it as a prop. Simply import useApp and start using it.

src/lib/component/toggle-btn.svelte
<script lang="ts">
	import { useApp } from "$lib/hooks/app.svelte.js";
	import { Button } from "$lib/components/ui/button";
	const app = useApp();
	/** Toggle light and dark mode when clicking the button */
	function onclick() {
		app.darkModeToggle();
	}
</script>

<Button {onclick}>Toggle theme</Button>