diff --git a/README.md b/README.md index 77b95f4e..edd8d3fc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@



- 🎣 + 👍
react-use
@@ -23,6 +23,12 @@ +## Install + +
+npm i react-use
+
+ ## Reference @@ -41,6 +47,7 @@ - [`useLocation`](./docs/useLocation.md) — tracks page navigation bar location state. - [`useMedia`](./docs/useMedia.md) — tracks state of a CSS media query. - [`useMediaDevices`](./docs/useMediaDevices.md) — tracks state of connected hardware devices. + - [`useMotion`](./docs/useMotion.md) — tracks state of device's motion sensor. - [`useNetwork`](./docs/useNetwork.md) — tracks state of user's internet connection. - [`useOrientation`](./docs/useOrientation.md) — tracks state of device's screen orientation. - [`useSize`](./docs/useSize.md) — tracks some HTML element's dimensions. @@ -53,6 +60,12 @@
+## Usage + +- You need to have React `16.7.0-alpha.0` or later installed to use Hooks API. +- You can import each hook individually `import useToggle from 'react-use/lib/useToggle'`. + + ## License [Unlicense](./LICENSE) — public domain. diff --git a/docs/useMotion.md b/docs/useMotion.md new file mode 100644 index 00000000..4089a198 --- /dev/null +++ b/docs/useMotion.md @@ -0,0 +1,20 @@ +# `useMotion` + +React sensor hook that uses device's acceleration sensor to track its motions. + + +## Usage + +```jsx +import {useMotion} from 'react-use'; + +const Demo = () => { + const state = useMotion(); + + return ( +
+      {JSON.stringify(state, null, 2)}
+    
+ ); +}; +``` diff --git a/src/__stories__/useMotion.story.tsx b/src/__stories__/useMotion.story.tsx new file mode 100644 index 00000000..8f1f1765 --- /dev/null +++ b/src/__stories__/useMotion.story.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import {storiesOf} from '@storybook/react'; +import {useMotion} from '..'; + +const Demo = () => { + const state = useMotion(); + + return ( +
+      {JSON.stringify(state, null, 2)}
+    
+ ); +}; + +storiesOf('useMotion', module) + .add('Example', () => + + ) diff --git a/src/index.ts b/src/index.ts index e9c7faca..ba694032 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ import useLocation from './useLocation'; import useMap from './useMap'; import useMedia from './useMedia'; import useMediaDevices from './useMediaDevices'; +import useMotion from './useMotion'; import useNetwork from './useNetwork'; import useOrientation from './useOrientation'; import useSize from './useSize'; @@ -26,6 +27,7 @@ export { useMap, useMedia, useMediaDevices, + useMotion, useNetwork, useOrientation, useSize, diff --git a/src/useMotion.ts b/src/useMotion.ts new file mode 100644 index 00000000..3955b64e --- /dev/null +++ b/src/useMotion.ts @@ -0,0 +1,84 @@ +import {useState, useEffect} from './react'; +import {on, off} from './util'; + +export interface MotionSensorState { + acceleration: { + x: number | null, + y: number | null, + z: number | null, + }, + accelerationIncludingGravity: { + x: number | null, + y: number | null, + z: number | null, + }, + rotationRate: { + alpha: number | null, + beta: number | null, + gamma: number | null, + }, + interval: number | null, +} + +const defaultState: MotionSensorState = { + acceleration: { + x: null, + y: null, + z: null, + }, + accelerationIncludingGravity: { + x: null, + y: null, + z: null, + }, + rotationRate: { + alpha: null, + beta: null, + gamma: null, + }, + interval: 16, +}; + +const useMotion = (initialState: MotionSensorState = defaultState) => { + const [state, setState] = useState(initialState); + + useEffect(() => { + const handler = (event) => { + const { + acceleration, + accelerationIncludingGravity, + rotationRate, + interval + } = event; + + setState({ + acceleration: { + x: acceleration.x, + y: acceleration.y, + z: acceleration.z + }, + accelerationIncludingGravity: { + x: accelerationIncludingGravity.x, + y: accelerationIncludingGravity.y, + z: accelerationIncludingGravity.z + }, + rotationRate: { + alpha: rotationRate.alpha, + beta: rotationRate.beta, + gamma: rotationRate.gamma, + }, + interval + }); + }; + + on(window, 'devicemotion', handler); + + return () => { + off(window, 'devicemotion', handler); + }; + }, [0]); + + return state; +}; + +export default useMotion;