-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improved hook performance, now works with safari. BREAKING CHANGE: `useNetwork` hook renamed to `useNetworkState`.
- Loading branch information
Showing
9 changed files
with
238 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# `useNetworkState` | ||
|
||
Tracks the state of browser's network connection. | ||
|
||
As of the standard it is not guaranteed that browser connected to the _Internet_, it only guarantees the network | ||
connection. | ||
|
||
## Usage | ||
|
||
```jsx | ||
import {useNetworkState} from 'react-use'; | ||
|
||
const Demo = () => { | ||
const state = useNetworkState(); | ||
|
||
return ( | ||
<pre> | ||
{JSON.stringify(state, null, 2)} | ||
</pre> | ||
); | ||
}; | ||
``` | ||
|
||
#### State interface: | ||
|
||
```typescript | ||
interface IUseNetworkState { | ||
/** | ||
* @desc Whether browser connected to the network or not. | ||
*/ | ||
online: boolean | undefined; | ||
/** | ||
* @desc Previous value of `online` property. Helps to identify if browser | ||
* just connected or lost connection. | ||
*/ | ||
previous: boolean | undefined; | ||
/** | ||
* @desc The {Date} object pointing to the moment when state change occurred. | ||
*/ | ||
since: Date | undefined; | ||
/** | ||
* @desc Effective bandwidth estimate in megabits per second, rounded to the | ||
* nearest multiple of 25 kilobits per seconds. | ||
*/ | ||
downlink: number | undefined; | ||
/** | ||
* @desc Maximum downlink speed, in megabits per second (Mbps), for the | ||
* underlying connection technology | ||
*/ | ||
downlinkMax: number | undefined; | ||
/** | ||
* @desc Effective type of the connection meaning one of 'slow-2g', '2g', '3g', or '4g'. | ||
* This value is determined using a combination of recently observed round-trip time | ||
* and downlink values. | ||
*/ | ||
effectiveType: 'slow-2g' | '2g' | '3g' | '4g' | undefined; | ||
/** | ||
* @desc Estimated effective round-trip time of the current connection, rounded | ||
* to the nearest multiple of 25 milliseconds | ||
*/ | ||
rtt: number | undefined; | ||
/** | ||
* @desc Wheter user has set a reduced data usage option on the user agent. | ||
*/ | ||
saveData: boolen | undefined; | ||
/** | ||
* @desc The type of connection a device is using to communicate with the network. | ||
*/ | ||
type: 'bluetooth' | 'cellular' | 'ethernet' | 'none' | 'wifi' | 'wimax' | 'other' | 'unknown' | undefined; | ||
} | ||
``` | ||
|
||
#### Call signature | ||
|
||
```typescript | ||
function useNetworkState(initialState?: IUseNetworkState | (() => IUseNetworkState)): IUseNetworkState; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import { useEffect, useState } from 'react'; | ||
import { off, on } from './misc/util'; | ||
import { IHookStateInitAction } from './misc/hookState'; | ||
|
||
export interface INetworkInformation extends EventTarget { | ||
readonly downlink: number; | ||
readonly downlinkMax: number; | ||
readonly effectiveType: 'slow-2g' | '2g' | '3g' | '4g'; | ||
readonly rtt: number; | ||
readonly saveData: boolean; | ||
readonly type: 'bluetooth' | 'cellular' | 'ethernet' | 'none' | 'wifi' | 'wimax' | 'other' | 'unknown'; | ||
|
||
onChange: (event: Event) => void; | ||
} | ||
|
||
export interface IUseNetworkState { | ||
/** | ||
* @desc Whether browser connected to the network or not. | ||
*/ | ||
online: boolean | undefined; | ||
/** | ||
* @desc Previous value of `online` property. Helps to identify if browser | ||
* just connected or lost connection. | ||
*/ | ||
previous: boolean | undefined; | ||
/** | ||
* @desc The {Date} object pointing to the moment when state change occurred. | ||
*/ | ||
since: Date | undefined; | ||
/** | ||
* @desc Effective bandwidth estimate in megabits per second, rounded to the | ||
* nearest multiple of 25 kilobits per seconds. | ||
*/ | ||
downlink: INetworkInformation['downlink'] | undefined; | ||
/** | ||
* @desc Maximum downlink speed, in megabits per second (Mbps), for the | ||
* underlying connection technology | ||
*/ | ||
downlinkMax: INetworkInformation['downlinkMax'] | undefined; | ||
/** | ||
* @desc Effective type of the connection meaning one of 'slow-2g', '2g', '3g', or '4g'. | ||
* This value is determined using a combination of recently observed round-trip time | ||
* and downlink values. | ||
*/ | ||
effectiveType: INetworkInformation['effectiveType'] | undefined; | ||
/** | ||
* @desc Estimated effective round-trip time of the current connection, rounded | ||
* to the nearest multiple of 25 milliseconds | ||
*/ | ||
rtt: INetworkInformation['rtt'] | undefined; | ||
/** | ||
* @desc {true} if the user has set a reduced data usage option on the user agent. | ||
*/ | ||
saveData: INetworkInformation['saveData'] | undefined; | ||
/** | ||
* @desc The type of connection a device is using to communicate with the network. | ||
* It will be one of the following values: | ||
* - bluetooth | ||
* - cellular | ||
* - ethernet | ||
* - none | ||
* - wifi | ||
* - wimax | ||
* - other | ||
* - unknown | ||
*/ | ||
type: INetworkInformation['type'] | undefined; | ||
} | ||
|
||
const nav: | ||
| (Navigator & Partial<Record<'connection' | 'mozConnection' | 'webkitConnection', INetworkInformation>>) | ||
| undefined = navigator; | ||
const conn: INetworkInformation | undefined = nav && (nav.connection || nav.mozConnection || nav.webkitConnection); | ||
|
||
function getConnectionState(previousState?: IUseNetworkState): IUseNetworkState { | ||
const online = nav?.onLine; | ||
const previousOnline = previousState?.online; | ||
|
||
return { | ||
online, | ||
previous: previousOnline, | ||
since: online !== previousOnline ? new Date() : previousState?.since, | ||
downlink: conn?.downlink, | ||
downlinkMax: conn?.downlinkMax, | ||
effectiveType: conn?.effectiveType, | ||
rtt: conn?.rtt, | ||
saveData: conn?.saveData, | ||
type: conn?.type, | ||
}; | ||
} | ||
|
||
export default function useNetworkState(initialState?: IHookStateInitAction<IUseNetworkState>): IUseNetworkState { | ||
const [state, setState] = useState(initialState ?? getConnectionState); | ||
|
||
useEffect(() => { | ||
const handleStateChange = () => { | ||
setState(getConnectionState); | ||
}; | ||
|
||
on(window, 'online', handleStateChange, { passive: true }); | ||
on(window, 'offline', handleStateChange, { passive: true }); | ||
|
||
if (conn) { | ||
on(conn, 'change', handleStateChange, { passive: true }); | ||
} | ||
|
||
return () => { | ||
off(window, 'online', handleStateChange); | ||
off(window, 'offline', handleStateChange); | ||
|
||
if (conn) { | ||
off(conn, 'change', handleStateChange); | ||
} | ||
}; | ||
}, []); | ||
|
||
return state; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,22 @@ | ||
import { storiesOf } from '@storybook/react'; | ||
import * as React from 'react'; | ||
import { useNetwork } from '../src'; | ||
import { useEffect } from 'react'; | ||
import { useNetworkState } from '../src'; | ||
import ShowDocs from './util/ShowDocs'; | ||
|
||
const Demo = () => { | ||
const state = useNetwork(); | ||
const state = useNetworkState(); | ||
|
||
return <pre>{JSON.stringify(state, null, 2)}</pre>; | ||
useEffect(() => { | ||
console.log(state); | ||
}, [state]) | ||
|
||
return <div> | ||
<div>Since JSON do not output `undefined` fields look the console to see whole the state</div> | ||
<pre>{JSON.stringify(state, null, 2)}</pre> | ||
</div>; | ||
}; | ||
|
||
storiesOf('Sensors/useNetwork', module) | ||
.add('Docs', () => <ShowDocs md={require('../docs/useNetwork.md')} />) | ||
storiesOf('Sensors/useNetworkState', module) | ||
.add('Docs', () => <ShowDocs md={require('../docs/useNetworkState.md')} />) | ||
.add('Demo', () => <Demo />); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
import { useNetworkState } from '../src'; | ||
|
||
//ToDo: improve tests | ||
describe(`useNetworkState`, () => { | ||
it('should be defined', () => { | ||
expect(useNetworkState).toBeDefined(); | ||
}); | ||
|
||
it('should return an object of certain structure', () => { | ||
const hook = renderHook(() => useNetworkState(), { initialProps: false }); | ||
|
||
expect(typeof hook.result.current).toEqual('object'); | ||
expect(Object.keys(hook.result.current)).toEqual([ | ||
'online', | ||
'previous', | ||
'since', | ||
'downlink', | ||
'downlinkMax', | ||
'effectiveType', | ||
'rtt', | ||
'saveData', | ||
'type', | ||
]); | ||
}); | ||
}); |