Обновление контекста

Haunted — это легковесная библиотека для создания веб-компонентов на основе реактивного подхода, вдохновленного React Hooks. Одним из ключевых аспектов эффективного использования Haunted является управление и обновление контекста, который обеспечивает передачу данных между компонентами без необходимости пробрасывать свойства через множество уровней.


Контекст и его создание

Контекст в Haunted создается с помощью функции createContext(). Она возвращает объект с двумя основными свойствами:

import { createContext } from 'haunted';

const ThemeContext = createContext({ color: 'blue' });
  • ThemeContext.Provider — компонент, который предоставляет значение контекста для всех дочерних компонентов.
  • ThemeContext.Consumer — хук или компонент для доступа к значению контекста внутри дочерних компонентов.

Контекст позволяет изолировать данные, которые могут меняться, и сделать их доступными для всех компонентов, находящихся в дереве под Provider.


Обновление значения контекста

Обновление контекста в Haunted строится вокруг реактивной модели. Основной способ — использование useState внутри Provider для управления состоянием:

import { useState } from 'haunted';

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState({ color: 'blue' });

  const toggleTheme = () => {
    setTheme(prev => ({ color: prev.color === 'blue' ? 'red' : 'blue' }));
  };

  return ThemeContext.Provider({ value: { theme, toggleTheme } }, children);
}
  • useState позволяет хранить текущее значение темы и автоматически инициировать перерисовку всех компонентов, использующих этот контекст.
  • Любое изменение через setTheme обновляет все дочерние компоненты, подписанные на контекст, без дополнительного кода.

Доступ к контексту внутри компонента

Для получения текущего значения контекста применяется хук useContext:

import { useContext } from 'haunted';

function Button() {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return html`<button style="color: ${theme.color}" @click=${toggleTheme}>
    Переключить тему
  </button>`;
}
  • useContext(ThemeContext) возвращает актуальное значение контекста.
  • Компонент автоматически перерисовывается при изменении данных в Provider.

Реактивное обновление и оптимизация

Haunted обеспечивает минимальные обновления, выполняя повторный рендер только тех компонентов, которые реально зависят от измененного значения. Для сложных приложений с глубокой иерархией компонентов важно учитывать несколько моментов:

  1. Избегать ненужных вычислений — значение контекста не должно пересоздаваться без необходимости.
  2. Мемоизация функций и объектовuseCallback и useMemo помогают предотвратить лишние обновления дочерних компонентов.

Пример мемоизации функции переключения темы:

import { useCallback } from 'haunted';

const toggleTheme = useCallback(() => {
  setTheme(prev => ({ color: prev.color === 'blue' ? 'red' : 'blue' }));
}, []);

Это гарантирует, что ссылка на функцию не меняется между рендерами, что уменьшает количество перерисовок дочерних элементов.


Динамическое обновление контекста

Haunted позволяет динамически изменять значение контекста в зависимости от внешних событий или асинхронных операций. Пример асинхронной загрузки настроек:

import { useEffect } from 'haunted';

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState({ color: 'blue' });

  useEffect(() => {
    fetch('/api/theme')
      .then(res => res.json())
      .then(data => setTheme(data));
  }, []);

  return ThemeContext.Provider({ value: { theme, setTheme } }, children);
}
  • useEffect обеспечивает выполнение побочных эффектов при монтировании компонента.
  • При обновлении состояния через setTheme все дочерние компоненты автоматически получают новое значение.

Вложенные провайдеры

Haunted поддерживает вложенные контексты. Вложенный Provider переопределяет значение родительского только для своих дочерних компонентов:

<ThemeContext.Provider value={{ color: 'blue' }}>
  <ComponentA />
  <ThemeContext.Provider value={{ color: 'green' }}>
    <ComponentB />
  </ThemeContext.Provider>
</ThemeContext.Provider>
  • ComponentA получит color: 'blue'.
  • ComponentB внутри вложенного Provider получит color: 'green'.

Это позволяет создавать гибкие конфигурации контекста для отдельных веток приложения.


Контроль перерисовок

Для больших приложений важно минимизировать лишние перерисовки. Основные приемы:

  • Разделение контекста на несколько мелких — лучше несколько специализированных контекстов, чем один общий с множеством полей.
  • Мемоизация объектов — всегда создавать новый объект только при реальном изменении значения.
const memoizedValue = useMemo(() => ({ theme, toggleTheme }), [theme]);
  • useMemo гарантирует, что объект контекста обновляется только при изменении theme, предотвращая ненужные обновления дочерних компонентов.

Итоговая структура

Типичная структура приложения с обновляемым контекстом выглядит так:

function App() {
  return html`
    <${ThemeProvider}>
      <${Header} />
      <${Content} />
      <${Footer} />
    <//>
  `;
}
  • Все компоненты Header, Content и Footer имеют доступ к актуальному значению темы через useContext.
  • Любое изменение состояния внутри ThemeProvider автоматически отражается в интерфейсе.

Контекст в Haunted сочетает простоту API с высокой реактивностью, позволяя создавать масштабируемые компоненты с минимальной связностью и управляемыми обновлениями состояния.