├── .gitignore ├── README.md ├── docs ├── assets │ └── react-icon.png ├── useAccessibilityInfo.md ├── useAppState.md ├── useBackHandler.md ├── useDimensions.md ├── useGeolocation.md ├── useKeyboard.md └── useNetInfo.md ├── hooks ├── useAccessibilityInfo.js ├── useAppState.js ├── useBackHandler.js ├── useDimensions.js ├── useGeolocation.js ├── useKeyboard.js └── useNetInfo.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # node.js 2 | # 3 | node_modules/ 4 | npm-debug.log 5 | yarn-error.log 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-use 2 | 3 | 4 | 5 | 🎣s for the React Native API 6 | 7 | This library is heavily inspired by [react-use](https://github.com/streamich/react-use) by [streamich](https://github.com/streamich). 8 | 9 | ## Installation 10 | 11 | ```bash 12 | yarn add react-native-use 13 | ``` 14 | 15 | ```bash 16 | npm i react-native-use 17 | ``` 18 | 19 | ------ 20 | 21 | ## Description 22 | 23 | Currently, this library contains hook implementations for the React Native API; however, it seeks to become a repository of hook recipes useful to RN devs. 24 | 25 | ------ 26 | 27 | ## Hooks 28 | 29 | ![rnlogo] [React Native API](https://facebook.github.io/react-native/) 30 | 31 | - [useAccessibilityInfo](./docs/useAccessibilityInfo.md) 32 | - [useAppState](./docs/useAppState.md) 33 | - [useBackHandler](./docs/useBackHandler.md) 34 | - [useDimensions](./docs/useDimensions.md) 35 | - [useGeolocation](./docs/useGeolocation.md) 36 | - [useKeyboard](./docs/useKeyboard.md) 37 | - [useNetInfo](./docs/useNetInfo.md) 38 | 39 | [rnlogo]: ./docs/assets/react-icon.png 40 | 41 | -------------------------------------------------------------------------------- /docs/assets/react-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alburdette619/react-native-use/10cbcc838878a08345181c8487d550ea0187f8d0/docs/assets/react-icon.png -------------------------------------------------------------------------------- /docs/useAccessibilityInfo.md: -------------------------------------------------------------------------------- 1 | # useAccessibilityInfo 2 | 3 | React Native API 🎣 that adds an event listener for the `AccessibilityInfo` `change` event, and adds one for the `announcementFinished` on iOS. Also, this will return the initial state from `AccessibilityInfo.fetch()` as well as the other methods for use with the API. 4 | 5 | ## Usage 6 | 7 | ```javascript 8 | import {useAccessibilityInfo} from 'react-native-use' 9 | 10 | const [ 11 | {readerEnabled, announcement, success}, 12 | setAccessibilityFocus, 13 | announceForAccessibility 14 | ] = useAccessibilityInfo(); 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/useAppState.md: -------------------------------------------------------------------------------- 1 | # useAppState 2 | 3 | React Native API 🎣 that adds an event listener for the `AppState` `change` event . Also, this will return the initial state from `AccessibilityInfo.currentState`. 4 | 5 | ## Usage 6 | 7 | ```javascript 8 | import {useAppState} from 'react-native-use' 9 | 10 | const appState = useAppState(); 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/useBackHandler.md: -------------------------------------------------------------------------------- 1 | # useBackHandler 2 | 3 | React Native API 🎣 that adds an event listener for the `BackHandler` `hardwareBackPress` event given a callback to use. 4 | 5 | ## Usage 6 | 7 | ```javascript 8 | import {useBackHandler} from 'react-native-use' 9 | 10 | const handleBackPress = () => { 11 | this.goBack(); 12 | return true; 13 | } 14 | 15 | useBackHandler(handleBackPress); 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/useDimensions.md: -------------------------------------------------------------------------------- 1 | # useDimensions 2 | 3 | React Native API 🎣 that adds event listener(s) for the `Dimsnsions` `change` event. Also, this will return the initial Dimensions when called. 4 | 5 | ## Types 6 | 7 | ### DimensionsTypes 8 | 9 | React Native has two dimensions, `screen` and `window`. On iOS these are the same, but on Android the values returned are different. From [the docs](https://facebook.github.io/react-native/docs/0.59/dimensions#get): 10 | 11 | > For Android the `window` dimension will exclude the size used by the `status bar` (if not translucent) and `bottom navigation bar` 12 | 13 | Any number of types can be requested, but defaults are set per Platform. 14 | 15 | | Type | **Defaults** | 16 | | :----- | :----------- | 17 | | SCREEN | Android | 18 | | WINDOW | Android, iOS | 19 | 20 | ## Usage 21 | 22 | ```javascript 23 | import {useDimensions, types} from 'react-native-use' 24 | 25 | const {DimensionsTypes} = types; 26 | const {window: {height, width}} = useDimensions(DimensionsTypes.WINDOW); 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/useGeolocation.md: -------------------------------------------------------------------------------- 1 | # useGeolocation 2 | 3 | React Native API 🎣 for the use of `navigator.geolocation`. It will return the initial state from `getCurrentPosition`. Watching can be setup as well. 4 | 5 | ## Usage 6 | 7 | ### Parameters 8 | 9 | Passed in as a single object with the following keys 10 | 11 | | Parameter Key | Required | Default Value | 12 | | ------------- | :------: | ------------- | 13 | | success | ☑ | - | 14 | | error | ☑ | - | 15 | | options | | {} | 16 | | shouldWatch | | False | 17 | 18 | ```javascript 19 | import {useGeolocation} from 'react-native-use' 20 | 21 | const success = location => console.log(location) 22 | const error = err => console.log(err) 23 | 24 | useGeolocation({success, error, options: {enableHighAccuracy: true}, shouldWatch: true}); 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/useKeyboard.md: -------------------------------------------------------------------------------- 1 | # useKeyboard 2 | 3 | React Native API 🎣 that adds event listener(s) for `Keyboard` events. 4 | 5 | ## Types 6 | 7 | ### KeyboardEventTypes 8 | 9 | React Native has six different event tyeps for the Keyboard API. 10 | 11 | Any number of types can be requested, by default, none are subscribed to. The following types can be used: 12 | 13 | - KEYBOARD_WILL_SHOW 14 | - KEYBOARD_DID_SHOW 15 | - KEYBOARD_WILL_HIDE 16 | - KEYBOARD_DID_HIDE 17 | - KEYBOARD_WILL_CHANGE_FRAME 18 | - KEYBOARD_DID_CHANGE_FRAME 19 | 20 | ## Usage 21 | 22 | ### Parameters 23 | 24 | Pass in a single object who's keys are `KeyboardEventTypes` and values are handlers for the specific keyboard events requested. 25 | 26 | ```javascript 27 | import {useKeyboard, types} from 'react-native-use' 28 | 29 | const {KeyboardEventTypes} = types; 30 | 31 | const handleKeyboardWillShow = () => console.log('Keyboard Will Show!') 32 | 33 | const keyboardState = useKeyboard({ 34 | KeyboardEventTypes.KEYBOARD_WILL_SHOW: handleKeyboardWillShow 35 | }); 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /docs/useNetInfo.md: -------------------------------------------------------------------------------- 1 | # useNetInfo 2 | 3 | React Native API 🎣 that adds an event listener to `NetInfo`. Also, this will return the initial state from `NetInfoInfo.fetch()`. 4 | 5 | ## Usage 6 | 7 | ```javascript 8 | import {useNetInfo} from 'react-native-use' 9 | 10 | const isConnected = useNetInfo(); 11 | ``` 12 | 13 | -------------------------------------------------------------------------------- /hooks/useAccessibilityInfo.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { AccessibilityInfo, Platform } from "react-native"; 3 | 4 | const useAccessibilityInfo = () => { 5 | const [state, setState] = useState(); 6 | const { setAccessibilityFocus, announceForAccessibility } = AccessibilityInfo; 7 | 8 | const handleStateChange = newState => setState({ ...state, ...newState }); 9 | const getInitialState = async () => 10 | handleStateChange({ readerEnabled: await AccessibilityInfo.fetch() }); 11 | 12 | useEffect(() => { 13 | getInitialState(); 14 | }, []); 15 | 16 | useEffect(() => { 17 | AccessibilityInfo.addEventListener("change", enabled => 18 | handleStateChange({ readerEnabled: enabled }) 19 | ); 20 | 21 | if (Platform.OS === "ios") { 22 | AccessibilityInfo.addEventListener( 23 | "announcementFinished", 24 | handleStateChange 25 | ); 26 | } 27 | 28 | return () => { 29 | AccessibilityInfo.removeEventListener("change", handleStateChange); 30 | 31 | if (Platform.OS === "ios") { 32 | AccessibilityInfo.removeEventListener( 33 | "announcementFinished", 34 | handleStateChange 35 | ); 36 | } 37 | }; 38 | }); 39 | 40 | return [state, setAccessibilityFocus, announceForAccessibility]; 41 | }; 42 | 43 | export default useAccessibilityInfo; 44 | -------------------------------------------------------------------------------- /hooks/useAppState.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { AppState } from "react-native"; 3 | 4 | const useAppState = () => { 5 | const [state, setState] = useState(AppState.currentState); 6 | const handleStateChange = state => setState(state); 7 | 8 | useEffect(() => { 9 | AppState.addEventListener("change", handleStateChange); 10 | 11 | return () => AppState.removeEventListener("change", handleStateChange); 12 | }); 13 | 14 | return state; 15 | }; 16 | 17 | export default useAppState; 18 | -------------------------------------------------------------------------------- /hooks/useBackHandler.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import { BackHandler } from "react-native"; 3 | 4 | const useBackHandler = handleBackPress => { 5 | useEffect(() => { 6 | BackHandler.addEventListener("hardwareBackPress", handleBackPress); 7 | 8 | return () => 9 | BackHandler.removeEventListener("hardwareBackPress", handleBackPress); 10 | }); 11 | 12 | return BackHandler.exitApp; 13 | }; 14 | 15 | export default useBackHandler; 16 | -------------------------------------------------------------------------------- /hooks/useDimensions.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Dimensions, Platform } from "react-native"; 3 | 4 | export const DimensionsTypes = { 5 | SCREEN: "screen", 6 | WINDOW: "window" 7 | }; 8 | 9 | const defaultTypes = Platform.select({ 10 | ios: [DimensionsTypes.WINDOW], 11 | android: Object.values(DimensionsTypes) 12 | }); 13 | 14 | const useDimensions = (types = defaultTypes) => { 15 | const typesArray = Array.isArray(types) ? types : [types]; 16 | 17 | const getDimensions = () => 18 | typesArray.reduce((acc, type) => { 19 | return { ...acc, [type]: Dimensions.get(type) }; 20 | }, {}); 21 | 22 | const initialState = getDimensions(); 23 | const [state, setState] = useState(initialState); 24 | const handleStateChange = () => setState(getDimensions()); 25 | 26 | useEffect(() => { 27 | Dimensions.addEventListener("change", handleStateChange); 28 | 29 | return () => Dimensions.removeEventListener("change", handleStateChange); 30 | }); 31 | 32 | return state; 33 | }; 34 | 35 | export default useDimensions; 36 | -------------------------------------------------------------------------------- /hooks/useGeolocation.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState, useCallback } from "react"; 2 | 3 | const useGeolocation = ({ 4 | success, 5 | error, 6 | options = {}, 7 | shouldWatch = false 8 | }) => { 9 | const { geolocation } = navigator; 10 | const [state, setState] = useState({}); 11 | 12 | const handleSuccess = useCallback( 13 | state => { 14 | setState(state); 15 | success(state); 16 | }, 17 | [state] 18 | ); 19 | const handleError = useCallback( 20 | state => { 21 | setState(state); 22 | error(state); 23 | }, 24 | [state] 25 | ); 26 | 27 | useEffect(() => { 28 | if (Object.keys(state).length === 0) { 29 | geolocation.getCurrentPosition(handleSuccess, handleError, options); 30 | } 31 | }); 32 | 33 | let watchId; 34 | if (shouldWatch) { 35 | useEffect(() => { 36 | watchId = geolocation.watchPosition(handleSuccess, handleError, options); 37 | 38 | return () => { 39 | geolocation.clearWatch(watchId); 40 | watchId = null; 41 | }; 42 | }); 43 | } else if (watchId) { 44 | geolocation.clearWatch(watchId); 45 | watchId = null; 46 | } 47 | }; 48 | 49 | export default useGeolocation; 50 | -------------------------------------------------------------------------------- /hooks/useKeyboard.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import { Keyboard } from "react-native"; 3 | 4 | export const KeyboardEventTypes = { 5 | KEYBOARD_WILL_SHOW: "keyboardWillShow", 6 | KEYBOARD_DID_SHOW: "keyboardDidShow", 7 | KEYBOARD_WILL_HIDE: "keyboardWillHide", 8 | KEYBOARD_DID_HIDE: "keyboardDidHide", 9 | KEYBOARD_WILL_CHANGE_FRAME: "keyboardWillChangeFrame", 10 | KEYBOARD_DID_CHANGE_FRAME: "keyboardDidChangeFrame" 11 | }; 12 | 13 | const useKeyboard = (handlers = []) => { 14 | const typesArray = Array.isArray(types) ? types : [types]; 15 | 16 | const handleStateChange = (newState, type) => 17 | handlers[type] && handlers[type](newState); 18 | 19 | useEffect(() => { 20 | typesArray.forEach(type => 21 | Keyboard.addListener(type, newState => handleStateChange(newState, type)) 22 | ); 23 | 24 | return () => typesArray.forEach(type => Keyboard.removeAllListeners(type)); 25 | }); 26 | }; 27 | 28 | export default useKeyboard; 29 | -------------------------------------------------------------------------------- /hooks/useNetInfo.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import NetInfo from "@react-native-community/netinfo"; 3 | 4 | const useNetInfo = () => { 5 | const [state, setState] = useState(); 6 | const handleStateChange = state => setState(state); 7 | const getInitialState = async () => handleStateChange(await NetInfo.fetch()); 8 | 9 | useEffect(() => { 10 | getInitialState(); 11 | }, []); 12 | 13 | useEffect(() => { 14 | const unSub = NetInfo.addEventListener(handleStateChange); 15 | 16 | return () => unSub; 17 | }); 18 | 19 | return state; 20 | }; 21 | 22 | export default useNetInfo; 23 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import useAccessibilityInfo from "./hooks/useAccessibilityInfo"; 2 | import useAppState from "./hooks/useAppState"; 3 | import useBackHandler from "./hooks/useBackHandler"; 4 | import useDimensions, { DimensionsTypes } from "./hooks/useDimensions"; 5 | import useGeolocation from "./hooks/useGeolocation"; 6 | import useKeyboard, { KeyboardEventTypes } from "./hooks/useKeyboard"; 7 | import useNetInfo from "./hooks/useNetInfo"; 8 | 9 | const types = { 10 | DimensionsTypes, 11 | KeyboardEventTypes 12 | }; 13 | 14 | export { 15 | useAccessibilityInfo, 16 | useAppState, 17 | useBackHandler, 18 | useDimensions, 19 | useGeolocation, 20 | useKeyboard, 21 | useNetInfo, 22 | types 23 | }; 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-use", 3 | "version": "1.1.0", 4 | "description": "Hooks for the React Native API", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/alburdette619/react-native-use.git" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "native", 16 | "react-native", 17 | "hooks" 18 | ], 19 | "author": "Adam Burdette", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/alburdette619/react-native-use/issues" 23 | }, 24 | "homepage": "https://github.com/alburdette619/react-native-use#readme" 25 | } 26 | --------------------------------------------------------------------------------