react-adaptive-hooks
Advanced tools
Comparing version 0.0.3 to 0.0.4
{ | ||
"name": "react-adaptive-hooks", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "Give users a great experience best suited to their device and network constraints", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
109
README.md
@@ -0,9 +1,8 @@ | ||
# React Adaptive Loading Hooks · ![](https://img.shields.io/github/license/GoogleChromeLabs/react-adaptive-hooks.svg) [![Build Status](https://travis-ci.org/GoogleChromeLabs/react-adaptive-hooks.svg?branch=master)](https://travis-ci.org/GoogleChromeLabs/react-adaptive-hooks) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/react-adaptive-hooks) | ||
# React Adaptive Loading Hooks | ||
> Deliver experiences best suited to a user's device and network constraints (experimental) | ||
> Give users a great experience best suited to their device and network constraints. | ||
This is a suite of [React Hooks](https://reactjs.org/docs/hooks-overview.html) for adaptive loading based on a user's: | ||
* [Network - effective connection type](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/effectiveType) | ||
* [Network via effective connection type](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/effectiveType) | ||
* [Data Saver preferences](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/saveData) | ||
@@ -28,10 +27,10 @@ * [Device memory](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory) | ||
```js | ||
import { useNetworkStatus } from './network'; | ||
import { useSaveData } from './save-data'; | ||
import { useHardwareConcurrency } from './hardware-concurrency'; | ||
import { useMemoryStatus } from './memory'; | ||
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 | ||
and then use them in your components. Examples for each hook can be found below. | ||
@@ -130,2 +129,92 @@ ### Network | ||
### Adaptive Code-loading & Code-splitting | ||
#### Code-loading | ||
Deliver a light, interactive core experience to users and progressively add high-end-only features on top, if a users hardware can handle it. Below is an example using the Network Status hook: | ||
```js | ||
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')); | ||
function MyComponent() { | ||
const { effectiveConnectionType } = useNetworkStatus(); | ||
return ( | ||
<div> | ||
<Suspense fallback={<div>Loading...</div>}> | ||
{ effectiveConnectionType === '4g' ? <Full /> : <Light /> } | ||
</Suspense> | ||
</div> | ||
); | ||
} | ||
export default MyComponent; | ||
``` | ||
Light.js: | ||
```js | ||
import React from 'react'; | ||
const Light = ({ imageUrl, ...rest }) => ( | ||
<img src={imageUrl} alt='product' {...rest} /> | ||
); | ||
export default Light; | ||
``` | ||
Full.js: | ||
```js | ||
import React from 'react'; | ||
import Magnifier from 'react-magnifier'; | ||
const Heavy = ({ imageUrl, ...rest }) => ( | ||
<Magnifier src={imageUrl} {...rest} /> | ||
); | ||
export default Full; | ||
``` | ||
#### Code-splitting | ||
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`). | ||
```js | ||
import React, { Suspense } from 'react'; | ||
const Component = React.lazy(() => { | ||
return new Promise(resolve => { | ||
navigator.connection ? resolve(navigator.connection.effectiveType) : resolve(null) | ||
}).then((effectiveType) => { | ||
switch (effectiveType) { | ||
case "3g": | ||
return import(/* webpackChunkName: "light" */ "./light.js"); | ||
break; | ||
case "4g": | ||
return import(/* webpackChunkName: "full" */ "./full.js"); | ||
break; | ||
default: | ||
return import(/* webpackChunkName: "full" */ "./full.js") | ||
} | ||
}); | ||
}); | ||
function App() { | ||
return ( | ||
<div className="App"> | ||
<header className="App-header"> | ||
<Suspense fallback={<div>Loading...</div>}> | ||
<Component /> | ||
</Suspense> | ||
</header> | ||
</div> | ||
); | ||
} | ||
export default App; | ||
``` | ||
## Browser Support | ||
@@ -187,2 +276,2 @@ | ||
This project is brought to you by [Addy Osmani](https://github.com/addyosmani) and [Anton Karlovskiy](https://github.com/anton-karlovskiy). | ||
This project is brought to you by [Addy Osmani](https://github.com/addyosmani) and [Anton Karlovskiy](https://github.com/anton-karlovskiy). |
38167
15
275