Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
react-adaptive-hooks
Advanced tools
Give users a great experience best suited to their device and network constraints
Deliver experiences best suited to a user's device and network constraints (experimental)
This is a suite of React Hooks and utilities for adaptive loading based on a user's:
It can be used to add patterns for adaptive resource loading, data-fetching, code-splitting and capability toggling.
Make it easier to target low-end devices while progressively adding high-end-only features on top. Using these hooks and utilities can help you give users a great experience best suited to their device and network constraints.
npm i react-adaptive-hooks --save
or yarn add react-adaptive-hooks
You can import the hooks you wish to use as follows:
import { useNetworkStatus } from 'react-adaptive-hooks/network';
import { useSaveData } from 'react-adaptive-hooks/save-data';
import { useHardwareConcurrency } from 'react-adaptive-hooks/hardware-concurrency';
import { useMemoryStatus } from 'react-adaptive-hooks/memory';
and then use them in your components. Examples for each hook and utility can be found below:
useNetworkStatus
React hook for adapting based on network status (effective connection type)
import React from 'react';
import { useNetworkStatus } from 'react-adaptive-hooks/network';
const MyComponent = () => {
const { effectiveConnectionType } = useNetworkStatus();
let media;
switch(effectiveConnectionType) {
case 'slow-2g':
media = <img src='...' alt='low resolution' />;
break;
case '2g':
media = <img src='...' alt='medium resolution' />;
break;
case '3g':
media = <img src='...' alt='high resolution' />;
break;
case '4g':
media = <video muted controls>...</video>;
break;
default:
media = <video muted controls>...</video>;
break;
}
return <div>{media}</div>;
};
effectiveConnectionType
values can be slow-2g
, 2g
, 3g
, or 4g
.
This hook accepts an optional initialEffectiveConnectionType
string argument, which can be used to provide a effectiveConnectionType
state value when the user's browser does not support the relevant NetworkInformation API. Passing an initial value can also prove useful for server-side rendering, where the developer can pass an ECT Client Hint to detect the effective network connection type.
// Inside of a functional React component
const initialEffectiveConnectionType = '4g';
const { effectiveConnectionType } = useNetworkStatus(initialEffectiveConnectionType);
useSaveData
utility for adapting based on the user's browser Data Saver preferences.
import React from 'react';
import { useSaveData } from 'react-adaptive-hooks/save-data';
const MyComponent = () => {
const { saveData } = useSaveData();
return (
<div>
{ saveData ? <img src='...' /> : <video muted controls>...</video> }
</div>
);
};
saveData
values can be true
or false
.
This hook accepts an optional initialSaveDataStatus
boolean argument, which can be used to provide a saveData
state value when the user's browser does not support the relevant NetworkInformation API. Passing an initial value can also prove useful for server-side rendering, where the developer can pass a server Save-Data Client Hint that has been converted to a boolean to detect the user's data saving preference.
// Inside of a functional React component
const initialSaveDataStatus = true;
const { saveData } = useSaveData(initialSaveDataStatus);
useHardwareConcurrency
utility for adapting to the number of logical CPU processor cores on the user's device.
import React from 'react';
import { useHardwareConcurrency } from 'react-adaptive-hooks/hardware-concurrency';
const MyComponent = () => {
const { numberOfLogicalProcessors } = useHardwareConcurrency();
return (
<div>
{ numberOfLogicalProcessors <= 4 ? <img src='...' /> : <video muted controls>...</video> }
</div>
);
};
numberOfLogicalProcessors
values can be the number of logical processors available to run threads on the user's device.
useMemoryStatus
utility for adapting based on the user's device memory (RAM)
import React from 'react';
import { useMemoryStatus } from 'react-adaptive-hooks/memory';
const MyComponent = () => {
const { deviceMemory } = useMemoryStatus();
return (
<div>
{ deviceMemory < 4 ? <img src='...' /> : <video muted controls>...</video> }
</div>
);
};
deviceMemory
values can be the approximate amount of device memory in gigabytes.
This hook accepts an optional initialMemoryStatus
object argument, which can be used to provide a deviceMemory
state value when the user's browser does not support the relevant DeviceMemory API. Passing an initial value can also prove useful for server-side rendering, where the developer can pass a server Device-Memory Client Hint to detect the memory capacity of the user's device.
// Inside of a functional React component
const initialMemoryStatus = { deviceMemory: 4 };
const { deviceMemory } = useMemoryStatus(initialMemoryStatus);
Deliver a light, interactive core experience to users and progressively add high-end-only features on top, if a user's hardware can handle it. Below is an example using the Network Status hook:
import React, { Suspense, lazy } from 'react';
import { useNetworkStatus } from 'react-adaptive-hooks/network';
const Full = lazy(() => import(/* webpackChunkName: "full" */ './Full.js'));
const Light = lazy(() => import(/* webpackChunkName: "light" */ './Light.js'));
const MyComponent = () => {
const { effectiveConnectionType } = useNetworkStatus();
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
{ effectiveConnectionType === '4g' ? <Full /> : <Light /> }
</Suspense>
</div>
);
};
export default MyComponent;
Light.js:
import React from 'react';
const Light = ({ imageUrl, ...rest }) => (
<img src={imageUrl} {...rest} />
);
export default Light;
Full.js:
import React from 'react';
import Magnifier from 'react-magnifier';
const Full = ({ imageUrl, ...rest }) => (
<Magnifier src={imageUrl} {...rest} />
);
export default Full;
We can extend React.lazy()
by incorporating a check for a device or network signal. Below is an example of network-aware code-splitting. This allows us to conditionally load a light core experience or full-fat experience depending on the user's effective connection speed (via navigator.connection.effectiveType
).
import React, { Suspense } from 'react';
const Component = React.lazy(() => {
const effectiveType = navigator.connection ? navigator.connection.effectiveType : null
let module;
switch (effectiveType) {
case '3g':
module = import(/* webpackChunkName: "light" */ './Light.js');
break;
case '4g':
module = import(/* webpackChunkName: "full" */ './Full.js');
break;
default:
module = import(/* webpackChunkName: "full" */ './Full.js');
break;
}
return module;
});
const App = () => {
return (
<div className='App'>
<Suspense fallback={<div>Loading...</div>}>
<Component />
</Suspense>
</div>
);
};
export default App;
Network Information API - effectiveType is available in Chrome 61+, Opera 48+, Edge 76+, Chrome for Android 76+, Firefox for Android 68+
Save Data API is available in Chrome 65+, Opera 62+, Chrome for Android 76+, Opera for Android 46+
Hardware Concurrency API is available in Chrome 37+, Safari 10.1+, Firefox 48+, Opera 24+, Edge 15+, Chrome for Android 76+, Safari on iOS 10.3+, Firefox for Android 68+, Opera for Android 46+
Performance memory API is a non-standard and only available in Chrome 7+, Opera, Chrome for Android 18+, Opera for Android
Device Memory API is available in Chrome 63+, Opera 50+, Chrome for Android 76+, Opera for Android 46+
Network-aware loading with create-react-app (Live)
Network-aware code-splitting with create-react-app (Live)
Network-aware data-fetching with create-react-app (Live)
Memory considerate loading with create-react-app (Live)
Memory considerate loading (SketchFab version) with create-react-app (Live)
Memory-considerate animation-toggling with create-next-app (Live)
Licensed under the Apache-2.0 license.
This project is brought to you by Addy Osmani and Anton Karlovskiy.
FAQs
Give users a great experience best suited to their device and network constraints
The npm package react-adaptive-hooks receives a total of 400 weekly downloads. As such, react-adaptive-hooks popularity was classified as not popular.
We found that react-adaptive-hooks demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.