
Обзор
Откройте для себя скрытый источник энергии в экосистеме 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