


Когда состояние живёт за пределами React, компоненту нужны чтение текущего значения и подписка на изменения. Для этой связи предназначен useSyncExternalStore. На Mentoring.digital разберём контракт на браузерном флаге подключения, не превращая его в обещание доступности сервера.
getSnapshot возвращает текущее значение, а subscribe принимает функцию уведомления React и возвращает очистку подписки. Функции вынесены за компонент, поэтому их ссылки не меняются при каждом рендере.
import { useSyncExternalStore } from "react";
function subscribe(onStoreChange) {
window.addEventListener("online", onStoreChange);
window.addEventListener("offline", onStoreChange);
return () => {
window.removeEventListener("online", onStoreChange);
window.removeEventListener("offline", onStoreChange);
};
}
function getSnapshot() {
return navigator.onLine;
}
function getServerSnapshot() {
return true;
}
export default function ConnectionHint() {
const online = useSyncExternalStore(
subscribe, getSnapshot, getServerSnapshot
);
return <p>{online
? "Браузер сообщает о подключении"
: "Браузер сообщает об отсутствии подключения"}</p>;
}
Пример предназначен для проекта React с обработкой JSX. Булево значение является удобным снимком: пока состояние не изменилось, его результат остаётся тем же при сравнении через Object.is.
Если getSnapshot на каждом вызове создаёт новый объект с теми же данными, React видит новое значение. Для изменяемого внешнего хранилища возвращайте закешированный неизменяемый снимок и создавайте следующий только после фактического изменения данных.
subscribe должен уведомлять React о возможном изменении. React затем перечитывает снимок. Очистка обязана снимать именно те слушатели, которые были добавлены: это важно при размонтировании и повторном подключении компонента.
Третий аргумент используется на сервере и при начальной гидратации в браузере. Его значение должно совпадать в этих двух точках. Здесь это намеренно выбранное исходное true, а не измеренное состояние сети пользователя. После подключения React читает настоящий браузерный снимок.
Для пользовательских данных передавайте согласованное начальное состояние вместе с серверной страницей. Не обращайтесь к window или navigator на сервере. Отсутствие getServerSnapshot при серверном рендеринге компонента приводит к ошибке.
В тестовом проекте переключите режим Offline в инструментах браузера и верните подключение. Затем скройте компонент и проверьте снятие слушателей. Если ваш источник возвращает объект, отдельно проверьте стабильность снимка без изменений.
navigator.onLine опирается на эвристики браузера. Значение true не доказывает доступность API приложения. Ошибку реального запроса обрабатывайте отдельно и не запрещайте действие только по этому флагу.
Подписки и рендеринг можно отработать на курсе React, а устройство внешнего хранилища обсудить с наставником по React.