Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Контекст: setContext и getContext

Контекст — способ передать значение от компонента всем его потомкам, на любую глубину, не протаскивая его через свойства каждого промежуточного компонента. В отличие от модуля .svelte.js, контекст принадлежит конкретному дереву компонентов, поэтому безопасен при серверной отрисовке.

Положить значение

Родитель кладёт значение функцией setContext(ключ, значение) из модуля svelte:

<!-- src/routes/+page.svelte -->
<script>
  import { setContext } from 'svelte';
  import TodoCounter from '$lib/components/TodoCounter.svelte';
 
  const todoStore = $state({
    items: [
      { id: 1, text: 'Купить хлеб', done: false },
      { id: 2, text: 'Позвонить Олегу', done: true }
    ]
  });
 
  setContext('todos', todoStore);
</script>
 
<h1>Мои задачи <TodoCounter /></h1>

Ключ — любая строка или символ. Значение — объект $state, чтобы потомки видели его изменения.

Получить значение

Любой вложенный компонент достаёт значение функцией getContext с тем же ключом:

<!-- src/lib/components/TodoCounter.svelte -->
<script>
  import { getContext } from 'svelte';
 
  const todoStore = getContext('todos');
  let remaining = $derived(todoStore.items.filter((t) => !t.done).length);
</script>
 
<span>Осталось: {remaining}</span>

В заголовке появится «Осталось: 1». TodoCounter не получает свойств: данные пришли через контекст.

Когда вызывать

setContext и getContext вызывают только при создании компонента — в начале блока <script>. В обработчике клика или в $effect они выдадут ошибку. Если значение нужно в обработчике, получите его заранее в переменную, как todoStore выше.

Удобные функции

Чтобы не повторять строковый ключ в разных файлах, обычно делают маленький модуль:

// src/lib/todo-context.js
import { getContext, setContext } from 'svelte';
 
const KEY = Symbol('todos');
 
export function setTodoContext(store) {
  setContext(KEY, store);
}
 
export function getTodoContext() {
  return getContext(KEY);
}

Теперь в +page.svelte пишут setTodoContext(todoStore), а в потомках — const todoStore = getTodoContext(). Опечатка в ключе больше невозможна.

Контекст или модуль .svelte.js

Модуль .svelte.jsКонтекст
Видимостьвся программапотомки одного компонента
На сервереобщий для всех посетителейсвой для каждого запроса
Где удобенсостояние только в браузереданные пользователя, темы, настройки дерева

Частая ошибка

Передать в контекст обычное значение и ждать обновлений:

<script>
  import { setContext } from 'svelte';
 
  let count = $state(0);
  setContext('count', count);
</script>

В контекст попадёт число 0 на момент вызова, и потомки не увидят дальнейших изменений. Передавайте объект $state (или функцию, возвращающую значение) и меняйте его свойства.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.