Skip to content

Commit 5ce329b

Browse files
authored
feat: Add React Native Web support (react-native-netinfo#292 by @jaulz)
1 parent 7d50056 commit 5ce329b

31 files changed

+3795
-201
lines changed

README.md

+21-17
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ To use this library you need to ensure you are using the correct version of Reac
153153
| `2.x.x` | `>= 0.57` |
154154
| `1.x.x` | `>= 0.57` |
155155

156+
## Browser Compatilibity
157+
The web implementation heavily depends on the [Network Information API](https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API) which is still an is an experimental technology and thus it's not supported in every browser.
158+
If this API is not available the library will safely fallback to the old [onLine](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine) property and return basic connection information.
159+
156160
## Migrating from the core `react-native` module
157161
This module was created when the NetInfo was split out from the core of React Native. To migrate to this module you need to follow the installation instructions above and then change you imports from:
158162

@@ -232,7 +236,7 @@ The `details` value depends on the `type` value.
232236

233237
| Property | Platform | Type | Description |
234238
| ----------------------- | ----------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
235-
| `isConnectionExpensive` | Android, iOS, Windows | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
239+
| `isConnectionExpensive` | Android, iOS, Windows, Web | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
236240
| `ssid` | Android, iOS (not tvOS) | `string` | The SSID of the network. May not be present, `null`, or an empty string if it cannot be determined. **On iOS, make sure your app meets at least one of the [following requirements](https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc#discussion). On Android, you need to have the `ACCESS_FINE_LOCATION` permission in your `AndroidManifest.xml` and accepted by the user**. |
237241
| `strength` | Android | `number` | An integer number from `0` to `5` for the signal strength. May not be present if the signal strength cannot be determined. |
238242
| `ipAddress` | Android, iOS | `string` | The external IP address. Can be in IPv4 or IPv6 format. May not be present if it cannot be determined. |
@@ -242,11 +246,11 @@ The `details` value depends on the `type` value.
242246

243247
`details` has these properties:
244248

245-
| Property | Platform | Type | Description |
246-
| ----------------------- | --------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
247-
| `isConnectionExpensive` | Android, iOS, Windows | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
248-
| `cellularGeneration` | Android, iOS, Windows | [`NetInfoCellularGeneration`](#netinfocellulargeneration) | The generation of the cell network the user is connected to. This can give an indication of speed, but no guarantees. |
249-
| `carrier` | Android, iOS | `string` | The network carrier name. May not be present or may be empty if none can be determined. |
249+
| Property | Platform | Type | Description |
250+
| ----------------------- | -------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
251+
| `isConnectionExpensive` | Android, iOS, Windows, Web | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
252+
| `cellularGeneration` | Android, iOS, Windows | [`NetInfoCellularGeneration`](#netinfocellulargeneration) | The generation of the cell network the user is connected to. This can give an indication of speed, but no guarantees. |
253+
| `carrier` | Android, iOS | `string` | The network carrier name. May not be present or may be empty if none can be determined. |
250254

251255
##### `type` is `bluetooth`, `ethernet`, `wimax`, `vpn`, or `other`
252256

@@ -259,17 +263,17 @@ The `details` value depends on the `type` value.
259263
#### `NetInfoStateType`
260264
Describes the current type of network connection. It is an enum with these possible values:
261265

262-
| Value | Platform | Description |
263-
| ----------- | --------------------- | ---------------------------------------------------------- |
264-
| `none` | Android, iOS, Windows | No network connection is active |
265-
| `unknown` | Android, iOS, Windows | The network state could not or has yet to be be determined |
266-
| `cellular` | Android, iOS, Windows | Active network over cellular |
267-
| `wifi` | Android, iOS, Windows | Active network over Wifi |
268-
| `bluetooth` | Android | Active network over Bluetooth |
269-
| `ethernet` | Android, Windows | Active network over wired ethernet |
270-
| `wimax` | Android | Active network over WiMax |
271-
| `vpn` | Android | Active network over VPN |
272-
| `other` | Android, iOS, Windows | Active network over another type of network |
266+
| Value | Platform | Description |
267+
| ----------- | -------------------------- | ---------------------------------------------------------- |
268+
| `none` | Android, iOS, Windows, Web | No network connection is active |
269+
| `unknown` | Android, iOS, Windows, Web | The network state could not or has yet to be be determined |
270+
| `cellular` | Android, iOS, Windows, Web | Active network over cellular |
271+
| `wifi` | Android, iOS, Windows, Web | Active network over Wifi |
272+
| `bluetooth` | Android, Web | Active network over Bluetooth |
273+
| `ethernet` | Android, Windows, Web | Active network over wired ethernet |
274+
| `wimax` | Android, Web | Active network over WiMax |
275+
| `vpn` | Android | Active network over VPN |
276+
| `other` | Android, iOS, Windows, Web | Active network over another type of network |
273277

274278
#### `NetInfoCellularGeneration`
275279
Describes the current generation of the `cellular` connection. It is an enum with these possible values:

example/e2e/sanityTest.spec.js example/e2e/sanityTest.spec.native.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*
77
* @format
88
*/
9+
/* eslint-env jest */
910

1011
const {device, expect, element, by} = require('detox');
1112

example/e2e/sanityTest.spec.web.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
*/
9+
/* eslint-env jest */
10+
11+
describe('NetInfo', () => {
12+
it('should have e2e tests in the future', async () => {
13+
await expect(true).toEqual(true);
14+
});
15+
});

example/e2e/testCases/Fetch.spec.js example/e2e/testCases/Fetch.spec.native.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*
77
* @format
88
*/
9+
/* eslint-env jest */
910

1011
const {device, expect, element, by} = require('detox');
1112

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
*/
9+
/* eslint-env jest */
10+
11+
describe('Fetch', () => {
12+
it('should have e2e tests in the future', async () => {
13+
await expect(true).toEqual(true);
14+
});
15+
});

example/e2e/testCases/HookInitialValue.spec.js example/e2e/testCases/HookInitialValue.spec.native.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*
77
* @format
88
*/
9+
/* eslint-env jest */
910

1011
const {device, expect, element, by} = require('detox');
1112

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
*/
9+
/* eslint-env jest */
10+
11+
describe('HookInitialValue', () => {
12+
it('should have e2e tests in the future', async () => {
13+
await expect(true).toEqual(true);
14+
});
15+
});

example/e2e/testCases/emitOnListen.spec.js example/e2e/testCases/emitOnListen.spec.native.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*
77
* @format
88
*/
9+
/* eslint-env jest */
910

1011
const {device, expect, element, by} = require('detox');
1112

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
*/
9+
/* eslint-env jest */
10+
11+
describe('EmitOnListen', () => {
12+
it('should have e2e tests in the future', async () => {
13+
await expect(true).toEqual(true);
14+
});
15+
});

example/index.html

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>react-native-netinfo</title>
6+
</head>
7+
<body>
8+
<noscript>You need to enable JavaScript to run this app.</noscript>
9+
<div id="root"></div>
10+
</body>
11+
</html>

example/index.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,10 @@ class ExampleApp extends React.Component<{}, State> {
200200
}
201201

202202
AppRegistry.registerComponent('NetInfoExample', () => ExampleApp);
203+
204+
// Run application on web
205+
if (typeof document !== 'undefined') {
206+
AppRegistry.runApplication('NetInfoExample', {
207+
rootTag: document.getElementById('root'),
208+
});
209+
}

example/webpack.config.js

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
* @flow
9+
*/
10+
11+
const path = require('path');
12+
const webpack = require('webpack');
13+
const babelConfig = require('./../babel.config');
14+
const HtmlWebpackPlugin = require('html-webpack-plugin');
15+
16+
module.exports = {
17+
entry: path.resolve(__dirname, 'index.tsx'),
18+
output: {
19+
path: path.resolve(__dirname, 'build'),
20+
filename: 'js/[name].bundle.js',
21+
},
22+
target: 'web',
23+
mode: 'development',
24+
devtool: 'source-map',
25+
resolve: {
26+
modules: [
27+
path.resolve(__dirname),
28+
path.resolve(__dirname, '..', 'node_modules'),
29+
],
30+
extensions: ['.web.tsx', '.tsx', '.web.ts', '.ts', '.web.js', '.js'],
31+
alias: {
32+
react: path.resolve(__dirname, '..', 'node_modules', 'react'),
33+
'react-native': path.resolve(
34+
__dirname,
35+
'..',
36+
'node_modules',
37+
'react-native-web',
38+
),
39+
},
40+
},
41+
module: {
42+
rules: [
43+
{
44+
test: /\.(ts|tsx)$/,
45+
loader: 'ts-loader',
46+
},
47+
{
48+
test: /\.m?js$/,
49+
use: {
50+
loader: 'babel-loader',
51+
options: babelConfig,
52+
},
53+
},
54+
{enforce: 'pre', test: /\.js$/, loader: 'source-map-loader'},
55+
],
56+
},
57+
plugins: [
58+
new HtmlWebpackPlugin({template: path.resolve(__dirname, 'index.html')}),
59+
new webpack.HotModuleReplacementPlugin(),
60+
],
61+
};
62+
/*
63+
module.exports = {
64+
context: __dirname,
65+
entry: {
66+
index: [
67+
'react-native-webpack/clients/polyfills.js',
68+
`./index.tsx`,
69+
],
70+
},
71+
devServer: {
72+
port: 8081,
73+
quiet: false,
74+
noInfo: true,
75+
lazy: true,
76+
filename: `[name].bundle`,
77+
watchOptions: {
78+
aggregateTimeout: 300,
79+
poll: 1000,
80+
},
81+
publicPath: '/',
82+
stats: { colors: true },
83+
},
84+
module: {
85+
rules: [
86+
{
87+
test: /\.tsx?$/,
88+
loader: 'ts-loader',
89+
exclude: /node_modules/,
90+
},
91+
]
92+
},
93+
resolve: {
94+
extensions: ['.web.tsx', ".tsx", '.web.ts', ".ts", '.web.js', ".js"]
95+
},
96+
};
97+
*/

jest.config.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ const { defaults: tsjPreset } = require('ts-jest/presets');
33

44
module.exports = {
55
...tsjPreset,
6-
preset: 'react-native',
6+
'projects': [
7+
{ 'preset': 'jest-expo/ios' },
8+
{ 'preset': 'jest-expo/android' },
9+
{ 'preset': 'jest-expo/web' },
10+
],
711
transform: {
812
...tsjPreset.transform,
913
'\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
@@ -14,7 +18,4 @@ module.exports = {
1418
babelConfig: true,
1519
},
1620
},
17-
setupFilesAfterEnv: [
18-
'<rootDir>/jest.setup.js',
19-
],
2021
};

jest.setup.js

-34
This file was deleted.

jest/netinfo-mock.js

+10
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,14 @@ const RNCNetInfoMock = {
99
removeListeners: jest.fn(),
1010
};
1111

12+
RNCNetInfoMock.getCurrentState.mockResolvedValue({
13+
type: 'cellular',
14+
isConnected: true,
15+
isInternetReachable: true,
16+
details: {
17+
isConnectionExpensive: true,
18+
cellularGeneration: '3g',
19+
},
20+
});
21+
1222
module.exports = RNCNetInfoMock;

package.json

+13-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"license": "MIT",
2525
"scripts": {
2626
"start": "react-native start",
27+
"start:web": "webpack-dev-server --config example/webpack.config.js",
2728
"test": "yarn validate:eslint && yarn validate:typescript && yarn test:jest",
2829
"validate:eslint": "eslint \"src/**/*.{js,ts,tsx}\" \"example/**/*.{js,ts,tsx}\"",
2930
"validate:typescript": "tsc --project ./ --noEmit",
@@ -63,23 +64,33 @@
6364
"@types/react-native": "^0.57.51",
6465
"@typescript-eslint/eslint-plugin": "^1.7.0",
6566
"@typescript-eslint/parser": "^1.7.0",
66-
"babel-jest": "^24.7.1",
67+
"babel-loader": "^8.0.6",
6768
"detox": "^12.8.0",
6869
"eslint": "5.16.0",
6970
"eslint-config-prettier": "^4.2.0",
7071
"eslint-plugin-prettier": "3.0.1",
72+
"html-webpack-plugin": "^3.2.0",
7173
"husky": "^2.3.0",
7274
"jest": "^24.8.0",
75+
"jest-expo": "^36.0.1",
76+
"jest-fetch-mock": "^3.0.1",
7377
"lint-staged": "^8.1.7",
7478
"metro-react-native-babel-preset": "^0.56.0",
7579
"prettier": "^1.17.0",
7680
"react": "16.9.0",
81+
"react-dom": "^16.12.0",
7782
"react-native": "0.61.2",
83+
"react-native-web": "^0.12.0",
7884
"react-test-renderer": "16.9.0",
7985
"rimraf": "^2.6.3",
8086
"semantic-release": "15.13.3",
87+
"source-map-loader": "^0.2.4",
8188
"ts-jest": "^24.0.2",
82-
"typescript": "^3.4.1"
89+
"ts-loader": "^6.2.1",
90+
"typescript": "^3.4.1",
91+
"webpack": "^4.41.5",
92+
"webpack-cli": "^3.3.10",
93+
"webpack-dev-server": "^3.10.2"
8394
},
8495
"detox": {
8596
"test-runner": "jest",

0 commit comments

Comments
 (0)