Svelte • Runtime
Context
On this page
Context allows components to access values owned by parent components without passing them down as props (potentially through many layers of intermediate components, known as ‘prop-drilling’).
By creating a [get, set] pair of functions with createContext, you can set the context in a parent component and get it in a child component:
<script lang="ts">
import type Parent = SvelteComponent<Record<string, any>, any, any>
const Parent: LegacyComponentType
Parent from './Parent.svelte';
import type Child = SvelteComponent<Record<string, any>, any, any>
const Child: LegacyComponentType
Child from './Child.svelte';
</script>
<const Parent: LegacyComponentTypeParent>
<const Child: LegacyComponentTypeChild />
</Parent><script>
import type Parent = SvelteComponent<Record<string, any>, any, any>
const Parent: LegacyComponentType
Parent from './Parent.svelte';
import type Child = SvelteComponent<Record<string, any>, any, any>
const Child: LegacyComponentType
Child from './Child.svelte';
</script>
<const Parent: LegacyComponentTypeParent>
<const Child: LegacyComponentTypeChild />
</Parent><script lang="ts">
import { setUserContext } from './context';
let { children } = $props();
setUserContext({ name: 'world' });
</script>
{@render children()}<script>
import { setUserContext } from './context';
let { children } = $props();
setUserContext({ name: 'world' });
</script>
{@render children()}<script lang="ts">
import { getUserContext } from './context';
const user = getUserContext();
</script>
<h1>hello {user.name}, inside Child.svelte</h1><script>
import { getUserContext } from './context';
const user = getUserContext();
</script>
<h1>hello {user.name}, inside Child.svelte</h1>import { function createContext<T>(): [() => T, (context: T) => T]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
function createContext<T>(): [() => T, (context: T) => T]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
createContext } from 'svelte';
interface User {
User.name: stringUser.name: stringname: string;
}
export const [const getUserContext: () => Userconst getUserContext: () => UsergetUserContext, const setUserContext: (context: User) => Userconst setUserContext: (context: User) => UsersetUserContext] = createContext<User>(): [() => User, (context: User) => User]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
createContext<User>(): [() => User, (context: User) => User]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
createContext<User>();
createContextwas added in version 5.40. If you are using an earlier version of Svelte, you must usesetContextandgetContextinstead.
This is particularly useful when Parent.svelte is not directly aware of Child.svelte, but instead renders it as part of a children snippet as shown above.
setContext and getContext
As an alternative to createContext, you can use setContext and getContext directly. The parent component sets context with setContext(key, value)…
<script lang="ts">
import { function setContext<T>(key: any, context: T): TAssociates an arbitrary context object with the current component and the specified key
and returns that object. The context is then available to children of the component
(including slotted content) with getContext.
Like lifecycle functions, this must be called during component initialisation.
createContext is a type-safe alternative.
setContext } from 'svelte';
setContext<"hello from Parent.svelte">(key: any, context: "hello from Parent.svelte"): "hello from Parent.svelte"Associates an arbitrary context object with the current component and the specified key
and returns that object. The context is then available to children of the component
(including slotted content) with getContext.
Like lifecycle functions, this must be called during component initialisation.
createContext is a type-safe alternative.
setContext('my-context', 'hello from Parent.svelte');
</script><script>
import { function setContext<T>(key: any, context: T): TAssociates an arbitrary context object with the current component and the specified key
and returns that object. The context is then available to children of the component
(including slotted content) with getContext.
Like lifecycle functions, this must be called during component initialisation.
createContext is a type-safe alternative.
setContext } from 'svelte';
setContext<"hello from Parent.svelte">(key: any, context: "hello from Parent.svelte"): "hello from Parent.svelte"Associates an arbitrary context object with the current component and the specified key
and returns that object. The context is then available to children of the component
(including slotted content) with getContext.
Like lifecycle functions, this must be called during component initialisation.
createContext is a type-safe alternative.
setContext('my-context', 'hello from Parent.svelte');
</script>…and the child retrieves it with getContext:
<script lang="ts">
import { function getContext<T>(key: any): TRetrieves the context that belongs to the closest parent component with the specified key.
Must be called during component initialisation.
createContext is a type-safe alternative.
getContext } from 'svelte';
const const message: unknownmessage = getContext<unknown>(key: any): unknownRetrieves the context that belongs to the closest parent component with the specified key.
Must be called during component initialisation.
createContext is a type-safe alternative.
getContext('my-context');
</script>
<h1>{const message: unknownmessage}, inside Child.svelte</h1><script>
import { function getContext<T>(key: any): TRetrieves the context that belongs to the closest parent component with the specified key.
Must be called during component initialisation.
createContext is a type-safe alternative.
getContext } from 'svelte';
const const message: unknownmessage = getContext<unknown>(key: any): unknownRetrieves the context that belongs to the closest parent component with the specified key.
Must be called during component initialisation.
createContext is a type-safe alternative.
getContext('my-context');
</script>
<h1>{const message: unknownmessage}, inside Child.svelte</h1>The key ('my-context', in the example above) and the context itself can be any JavaScript value.
createContextis preferred since it provides better type safety and makes it unnecessary to use keys.
In addition to setContext and getContext, Svelte exposes hasContext and getAllContexts functions.
Using context with state
You can store reactive state in context…
<script lang="ts">
import { setCounter } from './context.ts';
import Child from './Child.svelte';
let counter = $state({
count: 0
});
setCounter(counter);
</script>
<button onclick={() => counter.count += 1}>
increment
</button>
<Child />
<Child />
<Child />
<button onclick={() => counter.count = 0}>
reset
</button><script>
import { setCounter } from './context.ts';
import Child from './Child.svelte';
let counter = $state({
count: 0
});
setCounter(counter);
</script>
<button onclick={() => counter.count += 1}>
increment
</button>
<Child />
<Child />
<Child />
<button onclick={() => counter.count = 0}>
reset
</button><script lang="ts">
import { getCounter } from './context.ts';
const counter = getCounter();
</script>
<p>{counter.count}</p><script>
import { getCounter } from './context.ts';
const counter = getCounter();
</script>
<p>{counter.count}</p>import { function createContext<T>(): [() => T, (context: T) => T]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
function createContext<T>(): [() => T, (context: T) => T]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
createContext } from 'svelte';
interface Counter {
Counter.count: numberCounter.count: numbercount: number;
}
export const [const getCounter: () => Counterconst getCounter: () => CountergetCounter, const setCounter: (context: Counter) => Counterconst setCounter: (context: Counter) => CountersetCounter] = createContext<Counter>(): [() => Counter, (context: Counter) => Counter]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
createContext<Counter>(): [() => Counter, (context: Counter) => Counter]Returns a [get, set] pair of functions for working with context in a type-safe way.
get will throw an error if no parent component called set.
createContext<Counter>();…though note that if you reassign counter instead of updating it, you will ‘break the link’ — in other words instead of this…
<button onclick={() => counter = { count: 0 } }>
reset
</button>…you must do this:
<button onclick={() => counter.count = 0}>
reset
</button>Svelte will warn you if you get it wrong.
Similarly, to pass primitive values through context, use functions as described in Passing state into functions.
Component testing
When writing component tests, it can be useful to create a wrapper component that sets the context in order to check the behaviour of a component that uses it. As of version 5.49, you can do this sort of thing:
import { mount, unmount } from 'svelte';
import { expect, test } from 'vitest';
import { setUserContext } from './context';
import MyComponent from './MyComponent.svelte';
test('MyComponent', () => {
function Wrapper(...args) {
setUserContext({ name: 'Bob' });
return MyComponent(...args);
}
const component = mount(Wrapper, {
target: document.body
});
expect(document.body.innerHTML).toBe('<h1>Hello Bob!</h1>');
unmount(component);
});This approach also works with hydrate and render.
Replacing global state
When you have state shared by many different components, you might be tempted to put it in its own module and just import it wherever it’s needed:
export const const myGlobalState: {
user: {};
}
const myGlobalState: {
user: {};
}
myGlobalState = function $state<{
user: {};
}>(initial: {
user: {};
}): {
user: {};
} (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
function $state<{
user: {};
}>(initial: {
user: {};
}): {
user: {};
} (+1 overload)
namespace $state
Declares reactive state.
Example:
let count = $state(0);
$state({
user: {}user: {}user: {
// ...
}
// ...
});In many cases this is perfectly fine, but there is a risk: if you mutate the state during server-side rendering (which is discouraged, but entirely possible!)…
<script lang="ts">
import { myGlobalState } from './state.svelte.js';
let { data } = $props();
if (data.user) {
myGlobalState.user = data.user;
}
</script><script>
import { myGlobalState } from './state.svelte.js';
let { data } = $props();
if (data.user) {
myGlobalState.user = data.user;
}
</script>…then the data may be accessible by the next user. Context solves this problem because it is not shared between requests.