All hooks / Page, device, and user
useDeviceOrientation
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.
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(): DeviceOrientationStateReturns { 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
| Uses | Chrome | Edge | Firefox | Safari | Chrome Android | Safari iOS |
|---|---|---|---|---|---|---|
| deviceorientation eventWidely available | 7+ | 12+ | 6+ | 17+ | 18+ | 4.2+ |
| DeviceOrientationEvent.requestPermissionoptionalLimited availability | 152+ | 152+ | ✕ | ✕ | 152+ | 14.5+ |
- iOS needs
requestPermission()called from a tap. Desktops usually have no sensor, soorientationstaysnull.
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.