Skip to content

React-хуки ​

Импорт из os-detect/react. Требуется React 17+.

tsx
import { useOS, useIsWindows11, useFormFactor, useRuntime, usePrimaryInput } from 'os-detect/react'

Текущая ОС ​

useOS()

OS

Синхронно возвращает текущую строку ОС, вычисляется один раз через useState(() => getOS()) и стабильна между рендерами.

tsx
function Banner() {
  const os = useOS() // 'windows' | 'macos' | 'ios' | ...

  return <p>Running on {os}</p>
}

Определение Windows 11 ​

useIsWindows11()

boolean | null

Запускает асинхронную проверку detectIsWindows11() внутри useEffect и обновляет состояние при получении результата; значение — null, пока определение выполняется.

tsx
function WindowsBadge() {
  const isWin11 = useIsWindows11() // null → true | false

  if (isWin11 === null) return <Spinner />
  return <p>{isWin11 ? 'Windows 11' : 'Windows 10 или старше'}</p>
}

Форм-фактор ​

useFormFactor()

FormFactor

Вычисляется один раз через useState(() => getFormFactor()) и стабильна между рендерами.

tsx
function Layout() {
  const formFactor = useFormFactor() // 'phone' | 'tablet' | 'desktop' | 'tv' | 'unknown'

  return formFactor === 'phone' ? <MobileNav /> : <DesktopNav />
}

Рантайм-окружение ​

useRuntime()

Runtime

Вычисляется один раз через useState(() => getRuntime()) и стабильна между рендерами.

tsx
function DebugPanel() {
  const runtime = useRuntime() // 'node' | 'browser' | 'webworker' | 'unknown'

  return <p>Выполняется в: {runtime}</p>
}

Основной способ ввода ​

usePrimaryInput()

PrimaryInput

'unknown' до первого запуска useEffect, затем обновляется вживую. В отличие от useOS()/useFormFactor()/useRuntime(), этот хук по-настоящему реактивен: он слушает события изменения matchMedia('(pointer: …)') внутри useEffect и ре-рендерит компонент, если у гибридного устройства прямо во время сессии подключили или отключили клавиатуру/мышь.

tsx
function TapTargets() {
  const input = usePrimaryInput() // 'mouse' | 'touch' | 'unknown'

  return input === 'touch' ? <BigButtons /> : <CompactButtons />
}

SSR (Next.js) ​

useOS() вычисляет своё значение один раз через useState(() => getOS()), что выполняется во время рендера и на сервере тоже — при SSR это означает, что ОС сервера попадает в исходный HTML, а она может отличаться от клиентской, что может вызвать несовпадение при гидратации. useFormFactor() и useRuntime() следуют тому же паттерну и несут тот же риск. Если контент, зависящий от ОС, должен точно совпадать на клиенте, отложите его до useEffect:

tsx
import { useEffect, useState } from 'react'
import { getOS } from 'os-detect'
import type { OS } from 'os-detect'

function OSBanner() {
  const [os, setOS] = useState<OS | null>(null)

  useEffect(() => {
    setOS(getOS())
  }, [])

  if (!os) return null
  return <p>OS: {os}</p>
}

useIsWindows11() уже следует этому паттерну внутри себя (её результат разрешается внутри useEffect), поэтому ей этот обходной путь не нужен — как и usePrimaryInput(), по той же причине: она начинается со значения 'unknown' и впервые вызывает getPrimaryInput() только внутри useEffect.