Обзор
Откройте для себя скрытый источник энергии в экосистеме React: хук «useSyncExternalStore». В этой статье рассматривается его преобразующий потенциал, бросающий вызов традиционным парадигмам государственного управления. Бесшовно интегрируя внешние источники данных и улучшая взаимодействие между компонентами, этот хук предлагает нетрадиционный, но мощный подход.
Путешествуйте с нами, пока мы демистифицируем useSyncExternalStore
. Мы проанализируем его механику, раскроем его преимущества и продемонстрируем практическое применение на реальных примерах. К концу вы поймете, как использовать этот крючок, чтобы оптимизировать сложность, повысить производительность и вывести кодовую базу на новый уровень организации.
Применение
Согласно React, useSyncExternalStore
— это React Hook, который позволяет вам подписаться на внешний магазин. Но что такое «внешний магазин»? Он буквально выполняет 2 функции:
- Функция
subscribe
должна подписываться на хранилище и возвращать функцию, которая отменяет подписку. - Функция
getSnapshot
должна прочитать снимок данных из хранилища.
Ладно, поначалу может быть трудно получить. Мы можем перейти к примеру.
Демо
Для нашей сегодняшней демонстрации я зайду в классическое приложение: «Список дел».
Магазин
Во-первых, мы должны определить начальное состояние:
export type Task = { id: string; content: string; isDone: boolean; }; export type InitialState = { todos: Task[]; }; export const initialState: InitialState = { todos: [] };
Вы можете видеть, что я определил типы, а затем создал состояние, в котором todos
является пустым массивом.
Теперь редуктор:
export function reducer(state: InitialState, action: any) { switch (action.type) { case "ADD_TASK": const task = { content: action.payload, id: uid(), isDone: false, }; return { ...state, todos: [...state.todos, task], }; case "REMOVE_TASK": return { ...state, todos: state.todos.filter((task) => task.id !== action.payload), }; case "COMPLETE_TASK": const tasks = state.todos.map((task) => { if (task.id === action.payload) { task.isDone = !task.isDone; } return task; }); return { ...state, todos: tasks, }; default: return state; }
У нашего редуктора всего 3 действия: ADD_TASK
, REMOVE_TASK
и COMPLETE_TASK
. Это классический пример логики списка дел.
Наконец то, что мы ждем, магазин:
let listeners: any[] = []; function createStore(reducer: any, initialState: InitialState) { let state = initialState; function getState() { return state; } function dispatch(action: any) { state = reducer(state, action); emitChange(); } function subscribe(listener: any) { listeners = [...listeners, listener]; return () => { listeners = listeners.filter((l) => l !== listener); }; } const store = { dispatch, getState, subscribe, }; return store; } function emitChange() { for (let listener of listeners) { listener(); } } export const store = createStore(reducer, initialState);
Этот фрагмент кода иллюстрирует создание простой системы управления состоянием, похожей на Redux, в TypeScript. Вот описание того, как это работает:
listeners
Массив: этот массив содержит список функций прослушивателя, которые будут получать уведомления при каждом изменении состояния.createStore
Функция. Эта функция отвечает за создание магазина в стиле Redux. Он принимает два параметра:
reducer
: функция редуктора, отвечающая за вычисление следующего состояния на основе текущего состояния и отправленного действия.initialState
: исходное состояние приложения.
3. state
: эта переменная содержит текущее состояние приложения.
4. getState
Функция: возвращает текущее состояние.
5. Функция dispatch
: принимает объект действия, передает его редьюсеру вместе с текущим состоянием, обновляет состояние с результатом, а затем вызывает функцию emitChange
, чтобы уведомить слушателей об изменении состояния.
6. Функцияsubscribe
: принимает функцию прослушивателя, добавляет ее в массив listeners
и возвращает функцию очистки, которую можно вызвать для удаления прослушивателя.
7. Объектstore
: созданный объект хранилища содержит ссылки на функции dispatch
, getState
и subscribe
.
8. Функция emitChange
: перебирает массив listeners
и вызывает каждую функцию прослушивателя, уведомляя их об изменении состояния.
В конце кода с помощью функции createStore
создается store
с заданным редьюсером и начальным состоянием. Это хранилище теперь можно импортировать и использовать в других частях приложения для управления и контроля состояния.
Важно отметить, что этот код обеспечивает упрощенную реализацию системы управления состоянием и не имеет некоторых расширенных функций и оптимизаций, которые можно найти в таких библиотеках, как Redux. Тем не менее, он служит отличной отправной точкой для понимания основных концепций управления состоянием с использованием слушателей и функции редуктора.
Чтобы использовать крючок useSyncExternalStore
. Мы можем получить состояние следующим образом:
const { todos } = useSyncExternalStore(store.subscribe, store.getState);
С помощью этого вызова ловушки мы можем получить глобальный и динамический доступ к хранилищу, сохраняя при этом удобочитаемость и ремонтопригодность.
За и против
Хук «useSyncExternalStore» имеет как преимущества, так и потенциальные недостатки в контексте управления состоянием в приложении React:
Плюсы:
- Простая интеграция с внешними источниками. Этот хук обеспечивает простую интеграцию с внешними источниками данных, продвигая единый подход к управлению состоянием. Эта интеграция может упростить обработку данных из различных источников, повышая целостность приложения.
- Межкомпонентная связь. «useSyncExternalStore» обеспечивает эффективную связь между компонентами, оптимизируя обмен данными и снижая потребность в сложном детализации реквизитов или управлении контекстом.
- Улучшение производительности. Благодаря централизации управления состоянием и минимизации распространения обновлений состояния этот хук может оптимизировать производительность рендеринга, что приводит к более быстрому отклику и эффективности приложения.
- Простота и чистый код: абстрактный API хука может привести к более чистому и организованному коду, упрощая его понимание и поддержку, особенно в крупномасштабных приложениях.
- Сокращенный шаблон: «useSyncExternalStore» может уменьшить потребность в написании избыточного кода для управления состоянием, предоставляя краткий и последовательный способ управления состоянием всего приложения.
Минусы:
- Кривая обучения. Разработчики, не знакомые с этим крючком, могут столкнуться с кривой обучения при переходе с более устоявшихся решений для управления состоянием. Адаптация к новому подходу может изначально замедлить разработку.
- Ограничения настройки. Предопределенные функции хука могут не полностью соответствовать уникальным требованиям каждого приложения. Настройка поведения за пределами возможностей хука может потребовать дополнительных обходных путей.
- Потенциальные накладные расходы на абстракцию. В зависимости от своей внутренней механики хук может привести к небольшому увеличению производительности или использования памяти по сравнению с более оптимизированными решениями, разработанными специально для нужд приложения.
- Сообщество и экосистема. В качестве недооцененного или малоизвестного хука «useSyncExternalStore» может отсутствовать устоявшееся сообщество и комплексная экосистема, что может привести к уменьшению количества доступных ресурсов или сторонних библиотек.
- Совместимость и будущие обновления. Совместимость с будущими версиями React и потенциальные обновления самого хука могут вызывать беспокойство. Обеспечение долгосрочной поддержки и беспрепятственного обновления может потребовать особого внимания.
Заключение
Таким образом, useSyncExternalStore
предлагает уникальный подход к управлению состоянием с упором на бесшовную интеграцию и взаимодействие между компонентами. Хотя он обеспечивает несколько преимуществ, таких как повышенная производительность и упрощенный код, разработчики должны тщательно оценить его совместимость с требованиями своего проекта и рассмотреть потенциальную кривую обучения и ограничения.
Исходный код: https://github.com/superdev163/useSyncExternalStore