Skip to content

Commit ca4c586

Browse files
feat: add useNetInfoInstance - a non singleton-state hook to manage configs / events independently (#687)
1 parent a513f54 commit ca4c586

File tree

2 files changed

+137
-14
lines changed

2 files changed

+137
-14
lines changed

README.md

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,20 @@ import NetInfo from "@react-native-community/netinfo";
102102
Note that the API was updated after it was extracted from NetInfo to support some new features, however, the previous API is still available and works with no updates to your code.
103103

104104
## Usage
105-
Import the library:
106105

107-
```javascript
108-
import NetInfo from "@react-native-community/netinfo";
109-
```
106+
### Global vs isolated instance
107+
Internally this library has a network state manager class to handle all the functionality and state. This library provides two options for instantiating the class:
108+
1. you can use global library functions which taps into a global singleton instance of the class
109+
2. or you can create isolated instances of the class to tap into, each being separately configured
110110

111+
### Global instance functions:
111112
Subscribe to network state updates:
112113

113114
```javascript
115+
import { addEventListener } from "@react-native-community/netinfo";
116+
114117
// Subscribe
115-
const unsubscribe = NetInfo.addEventListener(state => {
118+
const unsubscribe = addEventListener(state => {
116119
console.log("Connection type", state.type);
117120
console.log("Is connected?", state.isConnected);
118121
});
@@ -124,22 +127,43 @@ unsubscribe();
124127
Get the network state once:
125128

126129
```javascript
127-
NetInfo.fetch().then(state => {
130+
import { fetch } from "@react-native-community/netinfo";
131+
132+
fetch().then(state => {
128133
console.log("Connection type", state.type);
129134
console.log("Is connected?", state.isConnected);
130135
});
131136
```
132137

138+
Get network state updates from the global instance via a react hook:
139+
140+
```javascript
141+
import { useNetInfo } from "@react-native-community/netinfo";
142+
143+
const { type, isConnected } = useNetInfo();
144+
```
145+
146+
### Isolated instance:
147+
Use an isolated instance of the network manager:
148+
149+
```javascript
150+
import { useNetInfoInstance } from "@react-native-community/netinfo";
151+
152+
const { netInfo: { type, isConnected }, refresh } = useNetInfoInstance();
153+
```
154+
133155
## API
134156
* **Types:**
135157
* [`NetInfoState`](#netinfostate)
136158
* [`NetInfoStateType`](#netinfostatetype)
137159
* [`NetInfoCellularGeneration`](#netinfocellulargeneration)
138-
* **Methods:**
160+
* **Global instance methods:**
139161
* [`fetch()`](#fetch)
140162
* [`refresh()`](#refresh)
141163
* [`addEventListener()`](#addeventlistener)
142164
* [`useNetInfo()`](#usenetinfo)
165+
* **Isolated instance:**
166+
* [`useNetInfoInstance()`](#usenetinfoinstance)
143167

144168
### Types
145169

@@ -241,7 +265,9 @@ The configuration options for the library.
241265
| `useNativeReachability` | `boolean` | `true` | A flag indicating whether or not Netinfo should use native reachability checks, if available.
242266

243267

244-
### Methods
268+
### Global instance methods
269+
270+
Please note the difference between global and isolated usage described [here](#global-vs-isolated-instance)
245271

246272
#### `configure()`
247273

@@ -285,7 +311,7 @@ unsubscribe();
285311

286312
#### `useNetInfo()`
287313

288-
A [React Hook](https://reactjs.org/docs/hooks-intro.html) which can be used to get access to the latest state. It returns a hook with the [`NetInfoState`](README.md#netinfostate) type.
314+
A [React Hook](https://reactjs.org/docs/hooks-intro.html) which can be used to get access to the latest state from the global instance. It returns a hook with the [`NetInfoState`](README.md#netinfostate) type.
289315

290316
**Example:**
291317
```jsx
@@ -358,6 +384,54 @@ NetInfo.refresh().then(state => {
358384
359385
This will also update subscribers using `addEventListener` and/or `useNetInfo`.
360386
387+
### Isolated instance
388+
389+
Please note the difference between global and isolated usage described [here](#global-vs-isolated-instance)
390+
391+
#### `useNetInfoInstance()`
392+
393+
A [React Hook](https://reactjs.org/docs/hooks-intro.html) which can be used to create and manage an isolated instance of a network manager class. It returns a `refresh` function and the current [`NetInfoState`](README.md#netinfostate).
394+
395+
**Example:**
396+
```jsx
397+
import { useNetInfoInstance } from "@react-native-community/netinfo";
398+
399+
const YourComponent = () => {
400+
const {netInfo, refresh} = useNetInfoInstance();
401+
402+
return (
403+
<View>
404+
<Text>Type: {netInfo.type}</Text>
405+
<Text>Is Connected? {netInfo.isConnected?.toString()}</Text>
406+
</View>
407+
);
408+
};
409+
```
410+
411+
**isPaused**: You can also pause the hooks internal network checks by passing a boolean value `true` as the first argument.
412+
413+
**configuration**: You can optionally send configuration as the second argument when setting up the hook. Note that configuration is local to the instance managed by this hook and has no relation to the configuration passed to other functions `configure()` or `useNetInfo()`;
414+
415+
```jsx
416+
import { useNetInfoInstance } from "@react-native-community/netinfo";
417+
418+
const YourComponent = () => {
419+
const isPaused = false;
420+
const config = {
421+
reachabilityUrl: 'https://clients3.google.com/generate_204',
422+
reachabilityTest: async (response) => response.status === 204,
423+
reachabilityLongTimeout: 60 * 1000, // 60s
424+
reachabilityShortTimeout: 5 * 1000, // 5s
425+
reachabilityRequestTimeout: 15 * 1000, // 15s
426+
reachabilityShouldRun: () => true,
427+
shouldFetchWiFiSSID: true, // met iOS requirements to get SSID
428+
useNativeReachability: false
429+
}
430+
431+
const { netInfo } = useNetInfoInstance(isPaused, config);
432+
//...
433+
```
434+
361435
## Troubleshooting
362436
363437
### Errors when building on Android

src/index.ts

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @format
88
*/
99

10-
import {useState, useEffect} from 'react';
10+
import {useState, useEffect, useCallback} from 'react';
1111
import {Platform} from 'react-native';
1212
import DEFAULT_CONFIGURATION from './internal/defaultConfiguration';
1313
import NativeInterface from './internal/nativeInterface';
@@ -26,7 +26,7 @@ const createState = (): State => {
2626
/**
2727
* Configures the library with the given configuration. Note that calling this will stop all
2828
* previously added listeners from being called again. It is best to call this right when your
29-
* application is started to avoid issues.
29+
* application is started to avoid issues. The configuration sets up a global singleton instance.
3030
*
3131
* @param configuration The new configuration to set.
3232
*/
@@ -50,6 +50,7 @@ export function configure(
5050

5151
/**
5252
* Returns a `Promise` that resolves to a `NetInfoState` object.
53+
* This function operates on the global singleton instance configured using `configure()`
5354
*
5455
* @param [requestedInterface] interface from which to obtain the information
5556
*
@@ -65,7 +66,7 @@ export function fetch(
6566
}
6667

6768
/**
68-
* Force-refreshes the internal state of the NetInfo library.
69+
* Force-refreshes the internal state of the global singleton managed by this library.
6970
*
7071
* @returns A Promise which contains the updated connection state.
7172
*/
@@ -77,7 +78,7 @@ export function refresh(): Promise<Types.NetInfoState> {
7778
}
7879

7980
/**
80-
* Subscribe to connection information. The callback is called with a parameter of type
81+
* Subscribe to the global singleton's connection information. The callback is called with a parameter of type
8182
* [`NetInfoState`](README.md#netinfostate) whenever the connection state changes. Your listener
8283
* will be called with the latest information soon after you subscribe and then with any
8384
* subsequent changes afterwards. You should not assume that the listener is called in the same
@@ -101,7 +102,9 @@ export function addEventListener(
101102
}
102103

103104
/**
104-
* A React Hook which updates when the connection state changes.
105+
* A React Hook into this library's singleton which updates when the connection state changes.
106+
*
107+
* @param {Partial<Types.NetInfoConfiguration>} configuration - Configure the isolated network checker managed by this hook
105108
*
106109
* @returns The connection state.
107110
*/
@@ -126,6 +129,51 @@ export function useNetInfo(
126129
return netInfo;
127130
}
128131

132+
/**
133+
* A React Hook which manages an isolated instance of the network info manager.
134+
* This is not a hook into a singleton shared state. NetInfo.configure, NetInfo.addEventListener,
135+
* NetInfo.fetch, NetInfo.refresh are performed on a global singleton and have no affect on this hook.
136+
* @param {boolean} isPaused - Pause the internal network checks.
137+
* @param {Partial<Types.NetInfoConfiguration>} configuration - Configure the isolated network checker managed by this hook
138+
*
139+
* @returns the netInfo state and a refresh function
140+
*/
141+
export function useNetInfoInstance(
142+
isPaused = false,
143+
configuration?: Partial<Types.NetInfoConfiguration>,
144+
) {
145+
const [networkInfoManager, setNetworkInfoManager] = useState<State>();
146+
const [netInfo, setNetInfo] = useState<Types.NetInfoState>({
147+
type: Types.NetInfoStateType.unknown,
148+
isConnected: null,
149+
isInternetReachable: null,
150+
details: null,
151+
});
152+
153+
useEffect(() => {
154+
if (isPaused) {
155+
return;
156+
}
157+
const config = {
158+
...DEFAULT_CONFIGURATION,
159+
...configuration,
160+
};
161+
const state = new State(config);
162+
setNetworkInfoManager(state);
163+
state.add(setNetInfo);
164+
return state.tearDown;
165+
}, [isPaused, configuration]);
166+
167+
const refresh = useCallback(() => {
168+
networkInfoManager && networkInfoManager._fetchCurrentState();
169+
}, [networkInfoManager]);
170+
171+
return {
172+
netInfo,
173+
refresh,
174+
};
175+
}
176+
129177
export * from './internal/types';
130178

131179
export default {
@@ -134,4 +182,5 @@ export default {
134182
refresh,
135183
addEventListener,
136184
useNetInfo,
185+
useNetInfoInstance,
137186
};

0 commit comments

Comments
 (0)