Open-source project
GoogleChromeLabs/react-adaptive-hooks avatar
GoogleChromeLabs/react-adaptive-hooks

react-adaptive-hooks: React Hooks for Network and Device-Adaptive Loading

Deliver experiences best suited to a user's device and network constraints

5,157 stars112 forksJavaScriptApache-2.0

At a glance

What is it?
react-adaptive-hooks is an experimental suite of React hooks from Google Chrome Labs that lets components adapt their rendering and resource loading based on the user's network connection type, data-saver preference, device memory, CPU core count, and media decoding capabilities. It is for React developers who need to serve lighter experiences on slow connections or low-end devices without rewriting their entire component tree.
Who is it for?
react-adaptive-hooks is worth considering for React applications where a single experience works poorly across the full range of devices and network conditions the app sees in production. The hooks expose platform signals that standard React does not abstract, and the initial-value mechanism handles SSR without changes to the hook interface.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 106 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What react-adaptive-hooks Solves for React Developers

A single rendered experience often works badly at the extremes of device capability. High-resolution video and complex JavaScript animations run smoothly on a flagship phone with a 4G connection and 8 GB of RAM. The same experience on a budget phone with a 2G connection and 512 MB of RAM produces slow loads and UI jank. Standard CSS media queries can respond to viewport size but not to network quality or device memory.

react-adaptive-hooks addresses this by exposing browser capability signals as React hooks. Each hook reads from a specific Web API and returns the current value, which a component can use to conditionally render lighter or heavier versions of its content. The README describes the objective as making it easier to target low-end devices while progressively adding high-end-only features on top.

The library is experimental, as the README states clearly in the project description. The package version is 0.1.0, and there are no GitHub releases. Google Chrome Labs published it to demonstrate the adaptive loading concept, and it is designed to be used as a reference implementation rather than as a hardened production library.

The Five Hooks and What Each Measures

The library provides five hooks, each targeting a different capability signal:

useNetworkStatus reads from the NetworkInformation API and returns the effective connection type, which can be `slow-2g`, `2g`, `3g`, or `4g`. This is not the user's contracted connection but the actual observed quality estimated by the browser.

useSaveData reads the user's Data Saver preference from the NetworkInformation API's `saveData` property and returns true or false. Data Saver mode indicates that the user or their carrier prefers reduced data usage.

useHardwareConcurrency reads `navigator.hardwareConcurrency` and returns the number of logical processor cores available. This can be used to avoid scheduling heavy parallel work on devices with few cores.

useMemoryStatus reads `navigator.deviceMemory` and returns the approximate RAM in gigabytes. The DeviceMemory API intentionally returns approximate values to reduce fingerprinting: the possible values are 0.25, 0.5, 1, 2, 4, and 8 gigabytes.

useMediaCapabilitiesDecodingInfo reads from the Media Capabilities API to check whether the device can decode a specific media format. The README gives the example of checking whether to serve WebM or fall back to MP4.

Installing and Using useNetworkStatus

Install the package with npm or yarn:

js
import { useNetworkStatus } from 'react-adaptive-hooks/network';

Each hook is imported from its own sub-path. In a component:

js
const { effectiveConnectionType } = useNetworkStatus();

The `effectiveConnectionType` value is one of `slow-2g`, `2g`, `3g`, or `4g`. A typical use case is to switch between a static image and a video based on connection quality. The README example shows a switch statement across all four values, serving progressively heavier media as the connection type improves toward 4g.

For server-side rendering, the hook accepts an optional initial value:

js
const initialEffectiveConnectionType = '4g';
const { effectiveConnectionType } = useNetworkStatus(initialEffectiveConnectionType);

Passing an initial value also works for clients whose browsers do not support the NetworkInformation API. The README notes that the initial value can be set from an ECT Client Hint header on the server, allowing the server to pass a detected connection type to the client-side hook state.

Device Memory and CPU Core Hooks

The memory and hardware-concurrency hooks follow the same pattern as useNetworkStatus. useMemoryStatus returns `deviceMemory` as an approximate gigabyte value:

js
const { deviceMemory } = useMemoryStatus();

A component can use this to skip heavy content on low-memory devices:

js
{ deviceMemory < 4 ?  : <video muted controls>...</video> }

useHardwareConcurrency returns `numberOfLogicalProcessors`:

js
const { numberOfLogicalProcessors } = useHardwareConcurrency();

Both hooks accept an optional initial value object for SSR or for browsers that do not support the underlying API. For useMemoryStatus:

js
const initialMemoryStatus = { deviceMemory: 4 };
const { deviceMemory } = useMemoryStatus(initialMemoryStatus);

The README points to the Server Device-Memory Client Hint for server-side detection, parallel to the ECT Client Hint used with useNetworkStatus. The memory and concurrency APIs may not be supported in all browsers, so the initial value fallback is often necessary.

Media Capabilities and the useMediaCapabilitiesDecodingInfo Hook

The Media Capabilities API exposes whether the current device can decode a specific video or audio configuration at full quality. useMediaCapabilitiesDecodingInfo takes a media decoding configuration object and returns information about whether the device can handle it smoothly and power-efficiently.

The README gives a specific use case: checking whether Safari can play WebM before serving a WebM video. If the browser supports WebM, serve WebM; if not, fall back to MP4. The hook handles this transparently: when the Media Capabilities API says the device cannot handle the preferred format, the component can switch to the fallback automatically, and when the device later gains support, the hook's return value changes accordingly.

The hook imports from a separate sub-path:

js
import { useMediaCapabilitiesDecodingInfo } from 'react-adaptive-hooks/media-capabilities';

The configuration object must match the MediaDecodingConfiguration interface, which specifies the type (file, record, transmission, or media-source), the content type string, and video dimensions and bitrate where applicable.

Browser API Coverage and What Happens When Support Is Missing

All five hooks depend on browser APIs that are not universally supported. The NetworkInformation API is not supported in Safari or Firefox as of the package's documentation. The DeviceMemory API has partial support across browsers. The Media Capabilities API has broader support but still has gaps.

The optional initial-value argument on each hook is the library's answer to this gap. When the browser does not support the underlying API, the hook returns the initial value rather than nothing, and the component renders based on that default. This is not a workaround for missing API support; it is the intended design. If no initial value is provided and the API is not available, the hook returns undefined, and the component must handle that case explicitly.

The package's peer dependencies require React ^16.8.0 or ^17.0.0. The package.json specifies these constraints. There is no documented support for React 18 or 19, and the README does not address concurrent mode compatibility. The package includes its own tests using @testing-library/react-hooks, and Jest handles the test runner.

Comparing react-adaptive-hooks to Using the Web APIs Directly

The Web APIs that react-adaptive-hooks wraps are available directly in browser JavaScript. A developer could read `navigator.connection.effectiveType` without any library. The library adds two things: subscription to API changes via React's useState and useEffect lifecycle, and the initial-value mechanism for SSR.

without the library, a component that reads navigator.connection.effectiveType at render time gets a single snapshot. The network connection can change during a session. The useNetworkStatus hook subscribes to the `change` event on the NetworkInformation object and updates the React state when the connection type changes, so the component re-renders automatically.

For teams that do not want a library dependency for five small hooks, the README is a workable reference for implementing the same pattern directly. Each hook is short, and the subscription logic for each API is straightforward. The library's value is in having the hooks already written, tested, and published as a package with the correct initial-value handling for SSR already included.

Editorial conclusion

react-adaptive-hooks is worth considering for React applications where a single experience works poorly across the full range of devices and network conditions the app sees in production. The hooks expose platform signals that standard React does not abstract, and the initial-value mechanism handles SSR without changes to the hook interface. The experimental label in the README is a real constraint: the package is at version 0.1.0 and has no GitHub releases, so the API may change. The last push was on 2026-06-16. Before adopting it, verify that your React version is ^16.8.0 or ^17.0.0, which are the supported peer dependencies, and check which of the underlying browser APIs are actually supported by your user population before designing features around them.

Frequently asked questions

Does react-adaptive-hooks work with server-side rendering?

Yes. Each hook accepts an optional initial value argument that is returned on the server or when the browser does not support the underlying API. The README shows how to pass a server-detected ECT Client Hint as the initialEffectiveConnectionType, and a Device-Memory Client Hint as the initialMemoryStatus.

What React versions does react-adaptive-hooks support?

The package.json specifies React ^16.8.0 or ^17.0.0 as peer dependencies. React 16.8 is the version that introduced hooks. No documentation in the repository covers React 18 or newer.

What happens in a browser that does not support the NetworkInformation API?

When the browser does not support the API, useNetworkStatus returns the initialEffectiveConnectionType value you passed, or undefined if you did not pass one. The hook does not throw an error; the component must handle the undefined case if no initial value is provided.

Official sources

  1. GoogleChromeLabs/react-adaptive-hooks on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/googlechromelabs-react-adaptive-hooks.svg)](https://hysenlabs.com/projects/googlechromelabs-react-adaptive-hooks)