useMediaQuery — это React-хук из библиотеки
Chakra UI, предназначенный для отслеживания
медиазапросов CSS непосредственно внутри компонентов. Он позволяет
реагировать на изменения размеров экрана, ориентации устройства,
цветовой схемы и других характеристик среды отображения.
Хук служит программным дополнением к адаптивным возможностям CSS и используется в ситуациях, когда поведение интерфейса должно изменяться не только визуально, но и логически.
Хук импортируется напрямую из пакета Chakra UI:
import { useMediaQuery } from "@chakra-ui/react"
Основная форма использования:
const [isLargerThan768] = useMediaQuery("(min-width: 768px)")
Аргументом передаётся строка с медиазапросом CSS.
Возвращаемое значение — массив булевых значений, где каждое значение соответствует одному медиазапросу.
Пример использования:
function Example() {
const [isDesktop] = useMediaQuery("(min-width: 1024px)")
return (
<div>
{isDesktop ? "Desktop view" : "Mobile view"}
</div>
)
}
При изменении ширины экрана React автоматически инициирует повторный рендер компонента.
useMediaQuery всегда возвращает массив,
даже если передан только один запрос.
const [matches] = useMediaQuery("(min-width: 768px)")
Тип возвращаемого значения:
boolean[]
Если передаётся несколько медиазапросов, каждый из них возвращает собственное булево значение.
Хук поддерживает одновременное отслеживание нескольких условий.
const [isTablet, isDesktop] = useMediaQuery([
"(min-width: 768px)",
"(min-width: 1024px)"
])
Использование:
function Layout() {
const [isTablet, isDesktop] = useMediaQuery([
"(min-width: 768px)",
"(min-width: 1200px)"
])
if (isDesktop) {
return <DesktopLayout />
}
if (isTablet) {
return <TabletLayout />
}
return <MobileLayout />
}
Такой подход удобен для программного управления адаптивными макетами.
Вторым аргументом можно передать объект конфигурации.
useMediaQuery(query, options)
Структура параметров:
{
ssr?: boolean
fallback?: boolean
}
ssrПри использовании серверного рендеринга (SSR) медиазапросы не могут
быть вычислены на сервере, поскольку отсутствует объект
window.
Поэтому Chakra UI позволяет указать поведение через параметр
ssr.
const [isDesktop] = useMediaQuery("(min-width: 1024px)", {
ssr: true
})
Если ssr: true, хук будет использовать значение
fallback до момента гидратации на клиенте.
fallbackfallback задаёт значение, которое будет возвращено на
сервере.
const [isDesktop] = useMediaQuery("(min-width: 1024px)", {
ssr: true,
fallback: false
})
На сервере значение будет равно false, а после загрузки
страницы на клиенте произойдёт пересчёт.
Это важно для предотвращения несоответствия HTML между сервером и клиентом.
Один из самых распространённых сценариев — проверка ширины экрана.
const [isMobile] = useMediaQuery("(max-width: 768px)")
Использование:
function Menu() {
const [isMobile] = useMediaQuery("(max-width: 768px)")
return (
<>
{isMobile ? <MobileMenu /> : <DesktopMenu />}
</>
)
}
Медиазапросы позволяют отслеживать ориентацию.
const [isLandscape] = useMediaQuery("(orientation: landscape)")
Пример:
function OrientationExample() {
const [isLandscape] = useMediaQuery("(orientation: landscape)")
return (
<div>
{isLandscape ? "Landscape mode" : "Portrait mode"}
</div>
)
}
Можно определять предпочтения пользователя по цветовой теме.
const [prefersDarkMode] = useMediaQuery("(prefers-color-scheme: dark)")
Пример:
function ThemeIndicator() {
const [prefersDarkMode] = useMediaQuery("(prefers-color-scheme: dark)")
return (
<div>
{prefersDarkMode ? "Dark mode preferred" : "Light mode preferred"}
</div>
)
}
Некоторые устройства не поддерживают hover-взаимодействие (например, сенсорные экраны).
const [hasHover] = useMediaQuery("(hover: hover)")
Пример:
function HoverExample() {
const [hasHover] = useMediaQuery("(hover: hover)")
return (
<div>
{hasHover ? "Mouse hover available" : "Touch device"}
</div>
)
}
Chakra UI уже имеет систему breakpoints:
sm: 30em
md: 48em
lg: 62em
xl: 80em
2xl: 96em
Эти значения можно использовать внутри медиазапросов.
const [isLarge] = useMediaQuery("(min-width: 62em)")
Однако в большинстве случаев для адаптивности Chakra UI предлагает
responsive props, поэтому useMediaQuery
применяется тогда, когда требуется логическая реакция в
JavaScript, а не только стили.
Хук позволяет избегать загрузки тяжёлых компонентов на маленьких устройствах.
function Dashboard() {
const [isDesktop] = useMediaQuery("(min-width: 1024px)")
return (
<>
<MainContent />
{isDesktop && <LargeAnalyticsPanel />}
</>
)
}
Это уменьшает нагрузку на мобильные устройства.
Иногда поведение интерфейса должно различаться между мобильными и десктопными версиями.
function Sidebar() {
const [isDesktop] = useMediaQuery("(min-width: 1024px)")
const mode = isDesktop ? "persistent" : "drawer"
return <Navigation mode={mode} />
}
В этом случае изменяется механика интерфейса, а не только его внешний вид.
useMediaQuery часто применяется при создании собственных
адаптивных хуков.
function useDeviceType() {
const [isTablet, isDesktop] = useMediaQuery([
"(min-width: 768px)",
"(min-width: 1200px)"
])
if (isDesktop) return "desktop"
if (isTablet) return "tablet"
return "mobile"
}
Применение:
function App() {
const device = useDeviceType()
return <div>Device: {device}</div>
}
Chakra UI предоставляет встроенную систему адаптивных свойств.
Пример:
<Box
fontSize={{ base: "14px", md: "18px", lg: "22px" }}
>
Такие свойства подходят для визуальных изменений.
useMediaQuery используется в других случаях:
Хук использует API браузера:
window.matchMedia()
Алгоритм работы:
MediaQueryListСхематично:
const mediaQuery = window.matchMedia(query)
setState(mediaQuery.matches)
mediaQuery.addEventListener("change", listener)
Chakra UI инкапсулирует этот механизм внутри React-хука.
Каждый вызов useMediaQuery создаёт собственный
listener.
При большом количестве компонентов рекомендуется:
Пример оптимизации:
function useIsDesktop() {
const [isDesktop] = useMediaQuery("(min-width: 1024px)")
return isDesktop
}
Хук возвращает массив, а не значение.
Неверно:
const isDesktop = useMediaQuery("(min-width: 1024px)")
Правильно:
const [isDesktop] = useMediaQuery("(min-width: 1024px)")
При использовании Next.js может возникнуть предупреждение о несоответствии HTML.
Решение:
useMediaQuery("(min-width: 1024px)", {
ssr: true,
fallback: false
})
Неправильно:
const [isDesktop] = useMediaQuery("(min-width: 1024px)")
const [isLarge] = useMediaQuery("(min-width: 1024px)")
Лучше использовать единый хук.
useMediaQueryПодходящие сценарии:
Хук занимает важное место в архитектуре адаптивных React-приложений, позволяя переносить медиазапросы из CSS в уровень программной логики интерфейса.