# react-native-community/hooks: React Native APIs as React Hooks

> A small TypeScript package that wraps AppState, Keyboard, BackHandler, Layout and other React Native APIs in hook form. Its API is stable and its documentation is thin, which matters more than the version number suggests.

**react-native-community/hooks** — React Native APIs turned into React Hooks for use in functional React components

- Repository: https://github.com/react-native-community/hooks
- Stars: 3,622 · Forks: 201
- Language: TypeScript
- License: ISC
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/react-native-community-hooks

## What react-native-community/hooks replaces in a functional component

React Native exposes most device and lifecycle state through imperative APIs. AppState has addEventListener and removeEventListener. Keyboard has show and hide events. BackHandler has addEventListener. Layout arrives through the onLayout prop on a View. In a class component you subscribe in componentDidMount and unsubscribe in componentWillUnmount. In a functional component there is no such place, so every developer writes the same useEffect with a subscription and a cleanup, and the same useState to hold the current value.

This package is a collection of those wrappers, published as @react-native-community/hooks. The README describes it as "React Native APIs turned into React Hooks allowing you to access asynchronous APIs directly in your functional components." The audience is narrow and obvious: React Native developers already on hooks, who would rather import a tested subscription than write one. It is not a state manager, not a UI kit, and not a replacement for React itself. The nine hooks listed in the README are the whole surface: useAccessibilityInfo, useAppState, useBackHandler, useImageDimensions, useKeyboard, useInteractionManager, useDeviceOrientation, useLayout and useRefresh.

## How the hooks are structured and what each one returns

The repository ships a single entry point. package.json sets "main": "lib/index.js" and "types": "lib/index.d.ts", so the package is compiled TypeScript with bundled type declarations, and the published files list is limited to lib with test files excluded. Source lives in src/ at the top level of the repository. There is no separate platform-specific directory structure described in the README, and the README does not document native modules, so the hooks appear to be pure JavaScript wrappers over the React Native APIs rather than anything requiring a native build step.

The return shapes differ by hook, which is the part worth reading carefully. useAppState returns a single string that the README says will be 'active', 'background', or, on iOS, 'inactive'. useInteractionManager returns a boolean. useDeviceOrientation returns a value the README logs without describing. useKeyboard returns an object with keyboardShown and keyboardHeight. useAccessibilityInfo returns six booleans, four of which (reduceMotionEnabled, grayscaleEnabled, invertColorsEnabled, reduceTransparencyEnabled) the README marks as requiring RN60 or newer. useImageDimensions returns an object with dimensions, loading and error, and dimensions in turn carries width, height and aspectRatio. useLayout returns onLayout plus the remaining layout fields spread alongside it, which is why the README destructures it as const { onLayout, ...layout } = useLayout(). useRefresh takes a function and returns isRefreshing and onRefresh.

The two hooks with the most interesting design are useBackHandler and useRefresh, because both invert control. useBackHandler takes a callback that returns true when the handler consumed the event and false to let the default behaviour proceed, and it takes a dependency array as a second argument. That return-a-boolean contract is the mechanism that lets multiple components cooperate on the Android back button without each one guessing whether another has already handled it. useRefresh takes your fetch function and manages the refreshing flag around it, so the RefreshControl wiring is reduced to two values from one hook call.

## Installing react-native-community/hooks and wiring a first hook

Install with npm or yarn. The README gives both forms and does not describe any additional native linking step, which is consistent with a package whose peerDependencies are only react and react-native.

```bash
npm install @react-native-community/hooks
```

The yarn equivalent is in the README as well.

```bash
yarn add @react-native-community/hooks
```

A first real use is useAppState, because it needs no props, no refs and no layout pass. Import it and call it at the top of a functional component; the returned value is the current app state string.

```js
import {useAppState} from '@react-native-community/hooks'

const currentAppState = useAppState()
```

The README states the value changes between 'active', 'background' and, on iOS, 'inactive' as the app moves between foreground and background. Log it and background the app to see it change.

A second use that exercises the callback contract is useBackHandler. The dependency array is required if your handler closes over changing values.

```js
import {useBackHandler} from '@react-native-community/hooks'

useBackHandler(() => {
  if (shouldBeHandledHere) {
    return true
  }
  return false
}, [shouldBeHandledHere])
```

Returning true tells the hook the event was consumed; returning false lets the default happen. If you skip the second argument, the handler is registered without a dependency list, which is a detail the README shows but does not explain.

## Where the package gets thin: versioning, compatibility and documentation

The version numbers are the first thing a careful reader notices. The published releases include v3.1.0, v100.0.1 and v100.1.0, all dated 2025-02-21. package.json currently declares "version": "100.1.0". A jump from 3.x to 100.x is not a normal semantic progression, and nothing in the README explains it. Treat the major number as meaningless for compatibility purposes and read the peerDependencies instead: react >=18.0.0 and react-native >=0.70. The README's own note says "You must use React Native >= 0.59.0", which contradicts the peerDependency floor of 0.70. When the README and package.json disagree, package.json is what your package manager will enforce, so the README note is stale.

The second thin area is documentation depth. The README is essentially an API index with one short example per hook. useDeviceOrientation is documented by a console.log of the value with no description of what that value can be. useInteractionManager returns a boolean the README prints but does not define in terms of when it flips. useImageDimensions is shown with a require() source and a {uri: ...} source, but the README does not say what happens on a failed remote fetch beyond the existence of an error field. There is no troubleshooting section, no migration guide, and no documented rollback path. For a package this small that may be acceptable, but it means the source in src/ is the real specification.

The third area is scope. There are nine hooks. If you need a hook for NetInfo, Dimensions changes, or anything else in the React Native API surface, this package does not have it, and the README does not describe an extension mechanism.

## When to write the subscription yourself instead

The wrong tool case is a component that needs behaviour the hook does not parameterise. useAppState returns the current state and nothing else. If you need to run different logic on the transition into 'background' versus the transition into 'active', the hook gives you the value but you still write a useEffect watching it, and at that point you have written most of the subscription anyway. The same applies to useKeyboard if you need the keyboard's screen coordinates or the event timing rather than just shown and height.

useImageDimensions is the hook most likely to be the wrong choice. It exists to resolve intrinsic dimensions from either a bundled asset or a remote URI, and it exposes loading and error. But the README's example returns null while loading, on error, or when dimensions are absent, which means the component renders nothing in all three cases. If you need a placeholder during loading and a distinct fallback on error, the hook's three-field return forces you to distinguish them yourself, and the README does not say how long the loading state persists or whether it re-resolves if the source prop changes identity on each render. Passing an inline object literal as the source is the kind of thing that would matter here, and the README does not address it.

useRefresh is a convenience wrapper, not a data layer. It takes your fetch function and manages isRefreshing around it. It does not deduplicate concurrent calls, does not cancel on unmount as far as the README describes, and does not surface errors, because its return is only isRefreshing and onRefresh. If your refresh path needs error state, use a query library instead.

## The alternative: React Native's own APIs and a hand-written hook

The realistic alternative is not another package. It is AppState, Keyboard, BackHandler and the onLayout prop used directly inside a useEffect you write. The difference in approach is ownership of the lifecycle. With this package you import a subscription someone else wrote and tested; with a hand-written hook you control exactly when the listener attaches, what dependencies it re-registers on, and what the cleanup does. React Native's own APIs are the same ones this package wraps, so there is no capability gap, only a difference in who maintains the subscription code and how much of it you repeat per hook.

The trade-off is concrete. Nine hooks' worth of subscription boilerplate is real code you would otherwise write and review. Against that, a hand-written hook can be shaped to your component's needs: return a tuple, expose the raw event, cancel a fetch on unmount. If you use three of these hooks, the package saves you three subscriptions. If you use one and need to customise it, the package is a dependency you are carrying for very little.

On the React side, the peerDependency floor is react >=18.0.0. That is a real constraint if you are maintaining an older app on React 17, because the package manager will warn or fail depending on your setup, and the README's RN 0.59 note will not help you there.

## Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-09-23. Releases are managed with Changesets, which the README credits and which package.json confirms through the release script: bun run typecheck && changeset publish. There is also a release:canary script that enters a canary pre-release, versions, and publishes with the canary tag. A renovate.json at the top level indicates automated dependency updates are configured. The practical effect is that version bumps arrive through changeset files rather than hand-edited version strings, and the changelog is generated from those files.

The licence is ISC, which package.json declares and the repository confirms with a LICENSE file. ISC is a permissive licence functionally similar to MIT: it permits use, modification and redistribution with the licence and copyright notice retained. That is a description of the terms, not legal advice; read the LICENSE file and your own organisation's policy if the distinction matters to you.

Upgrade cost is low in one direction and uncertain in another. Low, because the package has no native code, its published files are just lib, and its peer dependencies are React and React Native. Uncertain, because the 3.x to 100.x version jump means you cannot read the major number as a breaking-change signal. If you pin the version, pin it to an exact version rather than a caret range, and read CHANGELOG.md before moving between them.

## Conclusion

Adopt it if you are writing functional React Native components and want AppState, Keyboard, BackHandler or Layout state without hand-written subscriptions. Skip it if you need configuration beyond what the README shows, or if you depend on the package version as a compatibility signal. Before installing, check that your project meets the peerDependencies in package.json (react >=18.0.0, react-native >=0.70), and read the source under src/ for any hook whose return shape the README does not spell out, because that is the documentation you actually have.

## FAQ

### What React Native version does react-native-community/hooks require?

The README notes that you must use React Native >= 0.59.0, but package.json declares a peerDependency of react-native >=0.70 and react >=18.0.0. When these disagree, the peerDependencies in package.json are what your package manager enforces.

### How do I install react-native-community/hooks?

The README gives two commands: npm install @react-native-community/hooks, or yarn add @react-native-community/hooks. No additional native linking step is described.

### Which hooks does react-native-community/hooks provide?

The README lists nine: useAccessibilityInfo, useAppState, useBackHandler, useImageDimensions, useKeyboard, useInteractionManager, useDeviceOrientation, useLayout and useRefresh.

### Why is the version of react-native-community/hooks 100.1.0?

The published releases include v3.1.0, v100.0.1 and v100.1.0, all dated 2025-02-21, and package.json declares version 100.1.0. The README does not explain the jump from 3.x to 100.x.

### What does useBackHandler's callback return value mean?

The README's example returns true when the component handled the event and false to let the default thing happen. The hook takes a dependency array as its second argument.

### What licence is react-native-community/hooks under?

package.json declares "license": "ISC", and the repository contains a LICENSE file. ISC is a permissive licence that allows use and redistribution provided the notice is retained.

## Sources

- [Issues](https://github.com/react-native-community/hooks/issues)
- [License: ISC](https://github.com/react-native-community/hooks/blob/main/LICENSE)
- [react-native-community/hooks on GitHub](https://github.com/react-native-community/hooks)
- [README](https://github.com/react-native-community/hooks/blob/main/README.md)
- [Releases](https://github.com/react-native-community/hooks/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/react-native-community-hooks
