Encodera

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

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

Оглавление

Контекст

Контекст — способ передать данные всем вложенным компонентам сразу, не прокидывая их пропсами через каждый уровень. Обычно через контекст раздают то, что нужно во многих местах: список задач с функциями изменения, текущего пользователя, тему оформления.

Создание контекста

Создайте файл src/context/TodoContext.jsx. В нём будут сам контекст, компонент-поставщик и функция для чтения:

// src/context/TodoContext.jsx
import { createContext, useContext } from 'solid-js';
import { createStore } from 'solid-js/store';
 
const TodoContext = createContext();
 
export function TodoProvider(props) {
  const [todos, setTodos] = createStore([]);
 
  const add = (title) => setTodos(todos.length, { id: Date.now(), title, done: false });
  const toggle = (id) => setTodos((t) => t.id === id, 'done', (d) => !d);
 
  return (
    <TodoContext.Provider value={{ todos, add, toggle }}>
      {props.children}
    </TodoContext.Provider>
  );
}
 
export function useTodos() {
  return useContext(TodoContext);
}

TodoProvider создаёт хранилище и кладёт его вместе с функциями в атрибут value. Всё, что окажется внутри поставщика, сможет получить это значение.

Подключение поставщика

Оберните приложение в TodoProvider:

// src/App.jsx
import { TodoProvider } from './context/TodoContext';
import AddTodo from './components/AddTodo';
import TodoList from './components/TodoList';
 
export default function App() {
  return (
    <TodoProvider>
      <h1>Мои задачи</h1>
      <AddTodo />
      <TodoList />
    </TodoProvider>
  );
}

Чтение контекста

Компоненты внутри получают данные вызовом useTodos():

// src/components/TodoList.jsx
import { For } from 'solid-js';
import { useTodos } from '../context/TodoContext';
 
export default function TodoList() {
  const { todos, toggle } = useTodos();
 
  return (
    <ul>
      <For each={todos}>
        {(todo) => <li onClick={() => toggle(todo.id)}>{todo.title}</li>}
      </For>
    </ul>
  );
}
// src/components/AddTodo.jsx
import { useTodos } from '../context/TodoContext';
 
export default function AddTodo() {
  const { add } = useTodos();
 
  return <button onClick={() => add('Новая задача')}>Добавить</button>;
}

Нажатие на кнопку в AddTodo добавляет задачу, и она сразу появляется в TodoList, хотя эти компоненты не связаны пропсами. Деструктурировать значение контекста здесь можно: todos — хранилище, оно остаётся реактивным.

Что где лежит

ЧастьНазначение
createContext()Создаёт контекст
Context.ProviderЗадаёт значение для вложенных компонентов
useContext(Context)Читает значение

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

Вызывать useTodos() в компоненте, который находится вне TodoProvider, например прямо в App. Функция вернёт undefined, и обращение к todos выдаст ошибку. Поставщик должен быть выше по дереву, чем все компоненты, которые читают контекст.

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

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