All hooks / Page, device, and user

useDeviceOrientation

331 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

The device's orientation from its motion sensors: compass direction (alpha) and tilt (beta, gamma), updated as it moves.

On iOS the user must allow motion access, and the request only works from a tap: until then needsPermission is true, so show a button that calls requestPermission(). Browsers that don't require it (Chrome, Firefox) send readings right away, and needsPermission turns false on the first one. Laptops and desktops usually have no sensor, so orientation stays null. Re-renders on every reading, up to about 60 times a second.

Import

import { useDeviceOrientation } from '@vincent.ri/react-tils'
// or only this hook
import { useDeviceOrientation } from '@vincent.ri/react-tils/useDeviceOrientation'

Usage

const { orientation, needsPermission, requestPermission } = useDeviceOrientation()
if (needsPermission) return <button onClick={requestPermission}>Enable tilt</button>
const tilt = orientation?.gamma ?? 0
return <div style={{ transform: `rotate(${tilt}deg)` }}>🧭</div>

Live demo

On a phone, tilt it. Laptops usually have no sensor.

no readings

When to use it

Tilt effects, a compass, steering in a game, or a "level" tool.

When not to

You only need portrait or landscape; use useMediaQuery('(orientation: portrait)'). For the user's position, use useGeolocation.

API

function useDeviceOrientation(): DeviceOrientationState

Returns { orientation, needsPermission, requestPermission }.

Types

export type Orientation = {
  /** Compass direction around the vertical axis, 0 to 360 degrees. */
  alpha: number | null;
  /** Front-to-back tilt, -180 to 180 degrees. */
  beta: number | null;
  /** Left-to-right tilt, -90 to 90 degrees. */
  gamma: number | null;
};
export type DeviceOrientationState = {
  /** The latest reading, or `null` before the first one (and always on devices without the sensor). */
  orientation: Orientation | null;
  /** `true` while the browser may need permission and no reading has arrived (iOS until granted): show a button that calls `requestPermission`. */
  needsPermission: boolean;
  /** Ask for motion access on iOS. Must be called from a tap or click. Resolves to whether it was granted. */
  requestPermission: () => Promise<boolean>;
};

Browser support

UsesChromeEdgeFirefoxSafariChrome AndroidSafari iOS
deviceorientation eventWidely available7+12+6+17+18+4.2+
DeviceOrientationEvent.requestPermissionoptionalLimited availability152+152+✕✕152+14.5+
  • iOS needs requestPermission() called from a tap. Desktops usually have no sensor, so orientation stays null.

Optional features are used when present; without them the hook still works.

First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).

Coming from another library?

Other libraries call this useOrientation (react-use), useDeviceMotion, useGyroscope.