Skip to content

Commit 39a41c7

Browse files
committed
contex
1 parent ee80042 commit 39a41c7

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

apps/svelte.dev/content/docs/svelte/04-runtime/02-context.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,125 @@ title: Context
44

55
- get/set/hasContext
66
- how to use, best practises (like encapsulating them)
7+
8+
Most state is component-level state that lives as long as its component lives. There's also section-wide or app-wide state however, which also needs to be handled somehow.
9+
10+
The easiest way to do that is to create global state and just import that.
11+
12+
```ts
13+
/// file: state.svelte.ts
14+
15+
export const myGlobalState = $state({
16+
user: {
17+
/* ... */
18+
}
19+
/* ... */
20+
});
21+
```
22+
23+
```svelte
24+
<!--- file: App.svelte --->
25+
<script>
26+
import { myGlobalState } from './state.svelte';
27+
// ...
28+
</script>
29+
```
30+
31+
This has a few drawbacks though:
32+
33+
- it only safely works when your global state is only used client-side - for example, when you're building a single page application that does not render any of your components on the server. If your state ends up being managed and updated on the server, it could end up being shared between sessions and/or users, causing bugs
34+
- it may give the false impression that certain state is global when in reality it should only used in a certain part of your app
35+
36+
To solve these drawbacks, Svelte provides a few `context` primitives which alleviate these problems.
37+
38+
## Setting and getting context
39+
40+
To associate an arbitrary object with the current component, use `setContext`.
41+
42+
```svelte
43+
<script>
44+
import { setContext } from 'svelte';
45+
46+
setContext('key', value);
47+
</script>
48+
```
49+
50+
The context is then available to children of the component (including slotted content) with `getContext`.
51+
52+
```svelte
53+
<script>
54+
import { getContext } from 'svelte';
55+
56+
const value = getContext('key');
57+
</script>
58+
```
59+
60+
`setContext` and `getContext` solve the above problems:
61+
62+
- the state is not global, it's scoped to the component. That way it's safe to render your components on the server and not leak state
63+
- it's clear that the state is not global but rather scoped to a specific component tree and therefore can't be used in other parts of your app
64+
65+
> `setContext`/`getContext` must be called during component initialisation.
66+
67+
Context is not inherently reactive. If you need reactive values in context then you can pass a `$state` object into context, whos properties _will_ be reactive.
68+
69+
```svelte
70+
<!--- file: Parent.svelte --->
71+
<script>
72+
import { setContext } from 'svelte';
73+
74+
let value = $state({ count: 0 });
75+
setContext('counter', value);
76+
</script>
77+
78+
<button onclick={() => value.count++}>increment</button>
79+
```
80+
81+
```svelte
82+
<!--- file: Child.svelte --->
83+
<script>
84+
import { setContext } from 'svelte';
85+
86+
const value = setContext('counter');
87+
</script>
88+
89+
<p>Count is {value.count}</p>
90+
```
91+
92+
To check whether a given `key` has been set in the context of a parent component, use `hasContext`.
93+
94+
```svelte
95+
<script>
96+
import { hasContext } from 'svelte';
97+
98+
if (hasContext('key')) {
99+
// do something
100+
}
101+
</script>
102+
```
103+
104+
You can also retrieve the whole context map that belongs to the closest parent component using `getAllContexts`. This is useful, for example, if you programmatically create a component and want to pass the existing context to it.
105+
106+
```svelte
107+
<script>
108+
import { getAllContexts } from 'svelte';
109+
110+
const contexts = getAllContexts();
111+
</script>
112+
```
113+
114+
## Encapsulating context interactions
115+
116+
The above methods are very unopionated about how to use them. When your app grows in scale, it's worthwhile to encapsulate setting and getting the context into functions and properly type them.
117+
118+
```ts
119+
let userKey = new Symbol('user');
120+
121+
export function setUserContext(user: User) {
122+
setContext(userKey, user);
123+
}
124+
125+
export function setUserContext(): User {
126+
return getContext(userKey) as User;
127+
}
128+
```

0 commit comments

Comments
 (0)