Видеоуроки, интерактивный редактор и сохранение прогресса — бесплатно, сразу после входа.
ВойтиСоздать аккаунт — бесплатноЗакончили урок?
Войдите, чтобы отмечать прогресс
В этом решении мы выносим логику провайдера в компонент MailProvider и вводим хук useMail() для доступа к контексту. Снаружи остаются только <MailProvider> и useMail() — контекст и форма value скрыты внутри.
Контекст по-прежнему создаётся один раз и не экспортируется — к нему обращаются только провайдер и хук. useMail() вызывает useContext(MailContext) и возвращает значение; если провайдера нет (value равен null), выбрасывается ошибка с понятным текстом. Так вызывать useMail() снаружи MailProvider нельзя, и ошибка сразу укажет на место неправильного использования.
Вся логика провайдера сосредоточена в MailProvider: состояние выбора, список писем (в useMemo, чтобы ссылка не менялась), объект value для контекста (в useMemo с зависимостью [selectedId]). Компонент принимает только children и рендерит их внутри MailContext.Provider. Тот, кто использует MailProvider, не видит ни контекста, ни state, ни структуры value.
Вместо React.useContext(MailContext) компонент вызывает useMail() — так он получает те же данные, но через единый публичный API. Если InboxCount окажется вне MailProvider, сработает проверка в хуке и будет выброшена ошибка.
App не создаёт state, не формирует value и не знает про MailContext. Он только оборачивает дерево в <MailProvider> и рендерит дочерние компоненты. Детали контекста скрыты: снаружи видны только провайдер и хук useMail().