Socket
Socket
Sign inDemoInstall

react-detect-offline

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-detect-offline - npm Package Compare versions

Comparing version 2.0.1 to 2.1.0

.eslintrc.json

133

dist/index.js

@@ -12,4 +12,6 @@ "use strict";

var _react2 = _interopRequireDefault(_react);
var _propTypes = require("prop-types");
var _propTypes2 = _interopRequireDefault(_propTypes);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -28,11 +30,7 @@

var config = {
poll: unsupportedUserAgentsPattern.test(navigator.userAgent),
url: "https://ipv4.icanhazip.com/",
timeout: 5000,
interval: 5000
};
var ping = function ping(_ref) {
var url = _ref.url,
timeout = _ref.timeout;
var ping = function ping(config) {
return new Promise(function (resolve, reject) {
return new Promise(function (resolve) {
var isOnline = function isOnline() {

@@ -58,4 +56,4 @@ return resolve(true);

xhr.open("GET", config.url);
xhr.timeout = config.url;
xhr.timeout = timeout;
xhr.open("GET", url);
xhr.send();

@@ -65,2 +63,25 @@ });

var propTypes = {
children: _propTypes2.default.node,
onChange: _propTypes2.default.func,
polling: _propTypes2.default.oneOfType([_propTypes2.default.shape({
url: _propTypes2.default.string,
interval: _propTypes2.default.number,
timeout: _propTypes2.default.number
}), _propTypes2.default.bool]),
wrapperType: _propTypes2.default.string
};
var defaultProps = {
polling: true,
wrapperType: "span"
};
var defaultPollingConfig = {
enabled: unsupportedUserAgentsPattern.test(navigator.userAgent),
url: "https://ipv4.icanhazip.com/",
timeout: 5000,
interval: 5000
};
// base class that detects offline/online changes

@@ -86,11 +107,31 @@

_createClass(Base, [{
key: "componentDidMount",
value: function componentDidMount() {
window.addEventListener("online", this.goOnline);
window.addEventListener("offline", this.goOffline);
if (this.getPollingConfig().enabled) {
this.startPolling();
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
window.removeEventListener("online", this.goOnline);
window.removeEventListener("offline", this.goOffline);
if (this.pollingId) {
this.stopPolling();
}
}
}, {
key: "renderChildren",
value: function renderChildren() {
var children = this.props.children;
var _props$wrapperType = this.props.wrapperType,
wrapperType = _props$wrapperType === undefined ? "span" : _props$wrapperType;
var _props = this.props,
children = _props.children,
wrapperType = _props.wrapperType;
// usual case: one child that is a react Element
if (_react2.default.isValidElement(children)) {
if ((0, _react.isValidElement)(children)) {
return children;

@@ -105,8 +146,17 @@ }

// string children, multiple children, or something else
var childrenArray = _react.Children.toArray(children);
var firstChild = childrenArray[0];
return _react.createElement.apply(undefined, [wrapperType, {}].concat(_toConsumableArray(childrenArray)));
return _react.createElement.apply(undefined, [wrapperType, {}].concat(_toConsumableArray(_react.Children.toArray(children))));
}
}, {
key: "getPollingConfig",
value: function getPollingConfig() {
switch (this.props.polling) {
case true:
return defaultPollingConfig;
case false:
return { enabled: false };
default:
return Object.assign({}, defaultPollingConfig, this.props.polling);
}
}
}, {
key: "goOnline",

@@ -139,7 +189,14 @@ value: function goOnline() {

var _getPollingConfig = this.getPollingConfig(),
interval = _getPollingConfig.interval;
this.pollingId = setInterval(function () {
ping(config).then(function (online) {
var _getPollingConfig2 = _this2.getPollingConfig(),
url = _getPollingConfig2.url,
timeout = _getPollingConfig2.timeout;
ping({ url: url, timeout: timeout }).then(function (online) {
online ? _this2.goOnline() : _this2.goOffline();
});
}, config.interval);
}, interval);
}

@@ -151,22 +208,2 @@ }, {

}
}, {
key: "componentDidMount",
value: function componentDidMount() {
window.addEventListener("online", this.goOnline);
window.addEventListener("offline", this.goOffline);
if (config.poll) {
this.startPolling();
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
window.removeEventListener("online", this.goOnline);
window.removeEventListener("offline", this.goOffline);
if (config.poll) {
this.stopPolling();
}
}
}]);

@@ -177,2 +214,5 @@

Base.propTypes = propTypes;
Base.defaultProps = defaultProps;
var Online = exports.Online = function (_Base) {

@@ -197,2 +237,5 @@ _inherits(Online, _Base);

Online.propTypes = propTypes;
Online.defaultProps = defaultProps;
var Offline = exports.Offline = function (_Base2) {

@@ -217,2 +260,5 @@ _inherits(Offline, _Base2);

Offline.propTypes = propTypes;
Offline.defaultProps = defaultProps;
var Detector = exports.Detector = function (_Base3) {

@@ -236,1 +282,6 @@ _inherits(Detector, _Base3);

}(Base);
Detector.propTypes = Object.assign({}, propTypes, {
render: _propTypes2.default.func.isRequired
});
Detector.defaultProps = defaultProps;
{
"name": "react-detect-offline",
"version": "2.0.1",
"version": "2.1.0",
"description": "Offline and Online components for React",

@@ -14,2 +14,3 @@ "main": "dist/index.js",

"babel-cli": "^6.24.1",
"babel-eslint": "^8.2.2",
"babel-jest": "^21.0.0",

@@ -20,3 +21,12 @@ "babel-preset-es2015": "^6.24.1",

"enzyme-to-json": "^1.5.1",
"eslint": "^4.19.1",
"eslint-config-formidable": "^3.0.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-filenames": "^1.2.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-prettier": "^2.6.0",
"eslint-plugin-react": "^7.7.0",
"jest": "^21.0.1",
"prettier": "^1.11.1",
"prop-types": "^15.6.1",
"react": "^15.6.1",

@@ -31,4 +41,6 @@ "react-dom": "^15.6.1",

"scripts": {
"compile": "babel src/index.js -o dist/index.js",
"build": "babel src/index.js -o dist/index.js",
"test": "jest spec --watch",
"lint": "eslint src/ demo/src",
"prettier": "prettier src/** demo/src/** --write",
"test.cover": "jest spec --coverage"

@@ -35,0 +47,0 @@ },

@@ -11,3 +11,3 @@ [![npm](https://img.shields.io/npm/v/react-detect-offline.svg)](https://www.npmjs.com/package/react-detect-offline)

```jsx
import { Offline, Online } from 'react-detect-offline';
import { Offline, Online } from "react-detect-offline";

@@ -24,21 +24,35 @@ const App = () => (

Check out [chris.bolin.co/offline](https://chris.bolin.co/offline) for a simple example ([source code](https://github.com/chrisbolin/offline/blob/master/src/App.js)). As in this example, `react-detect-offline` pairs well with [`create-react-app`](https://github.com/facebookincubator/create-react-app), which creates offline-ready React apps out of the box.
Check out [chris.bolin.co/offline](https://chris.bolin.co/offline) for a simple example ([source code](https://github.com/chrisbolin/offline/blob/master/src/App.js)).
### API
### Components
`<Online/>` - Component that renders its children only when the browser is online.
`<Online/>` - Component that renders its children only when the browser is online. _Recommended for simple use cases._
`<Offline/>` - Component that renders its children only when the browser is not online.
`<Offline/>` - Component that renders its children only when the browser is not online. _Recommended for simple use cases._
**Note:** `Online` and `Offline` are mutually exclusive; if one is rendering, the other will not be.
`<Detector render={({ online }) => ...}/>` - Component that calls its `render` prop every time the connection state changes. The `render` prop is supplied with an object with an `online` boolean value. _Recommended for more complex cases, e.g. when styles need to be changed with connection status._
### Browser Support
### Props
The [web spec](https://developer.mozilla.org/en-US/docs/Online_and_offline_events) we rely on is supported by IE 9+, Chrome 14+, Firefox 41+, and Safari 5+ - that's [94% of worldwide (98% of US)](http://caniuse.com/#feat=online-status) browser traffic.
`<Online/>`, `<Offline/>`, and `<Detector/>` accept the following props:
### Example Uses
| Prop | Type | Description | Default |
| ------------------ | ----------- | --------------------------------- | ------------------------------ |
| `polling` | Obj or Bool | Config for polling fallback [1] | [see below] |
| `polling.enabled` | Boolean | Force polling on or off | Depends on the browser [1] |
| `polling.url` | String | URL to pool for connection status | `"https://ipv4.icanhazip.com"` |
| `polling.interval` | Number | How often (in ms) to poll | `5000` |
| `polling.timeout` | Number | How long (in ms) before timeout | `5000` |
| `onChange` | Function | Called when connection changes | none |
| `children` [2] | Element(s) | Children **not Detector** | none |
| `render` [3] | Func | Render function **Detector only** | none |
- Use `Offline` to remind users they might need to connect to complete certain actions.
- Use `Online` to let readers know the page is available offline.
- Use `Online` to hide links or other content that is irrelevant when offline.
- idk, use your dang imagination.
[1] Polling is only used as a fallback for browsers that don't support the `"online"` event. Currently these are Chrome on Windows, Firefox on Windows, and Chrome on Linux.
[2] `<Online/>` and `<Offline/>` only. `<Detector/>` will not render `children`.
[3] `<Detector/>` only
### Browser Support
The [web spec](https://developer.mozilla.org/en-US/docs/Online_and_offline_events) we rely on is supported by IE 9+, Chrome 14+, Firefox 41+, and Safari 5+ - that's [94% of worldwide (98% of US)](http://caniuse.com/#feat=online-status) browser traffic. A polling fallback is used for browsers that don't implement the spec in a useful way (see note [1] in the above Props section).

@@ -1,7 +0,3 @@

import React, {
Component,
isValidElement,
Children,
createElement
} from "react";
import { Component, isValidElement, Children, createElement } from "react";
import PropTypes from "prop-types";

@@ -11,11 +7,4 @@ // these browsers don't fully support navigator.onLine, so we need to use a polling backup

const config = {
poll: unsupportedUserAgentsPattern.test(navigator.userAgent),
url: "https://ipv4.icanhazip.com/",
timeout: 5000,
interval: 5000
};
const ping = config => {
return new Promise((resolve, reject) => {
const ping = ({ url, timeout }) => {
return new Promise(resolve => {
const isOnline = () => resolve(true);

@@ -37,4 +26,4 @@ const isOffline = () => resolve(false);

xhr.open("GET", config.url);
xhr.timeout = config.url;
xhr.timeout = timeout;
xhr.open("GET", url);
xhr.send();

@@ -44,2 +33,28 @@ });

const propTypes = {
children: PropTypes.node,
onChange: PropTypes.func,
polling: PropTypes.oneOfType([
PropTypes.shape({
url: PropTypes.string,
interval: PropTypes.number,
timeout: PropTypes.number
}),
PropTypes.bool
]),
wrapperType: PropTypes.string
};
const defaultProps = {
polling: true,
wrapperType: "span"
};
const defaultPollingConfig = {
enabled: unsupportedUserAgentsPattern.test(navigator.userAgent),
url: "https://ipv4.icanhazip.com/",
timeout: 5000,
interval: 5000
};
// base class that detects offline/online changes

@@ -57,8 +72,25 @@ class Base extends Component {

componentDidMount() {
window.addEventListener("online", this.goOnline);
window.addEventListener("offline", this.goOffline);
if (this.getPollingConfig().enabled) {
this.startPolling();
}
}
componentWillUnmount() {
window.removeEventListener("online", this.goOnline);
window.removeEventListener("offline", this.goOffline);
if (this.pollingId) {
this.stopPolling();
}
}
renderChildren() {
const { children } = this.props;
const { wrapperType = "span" } = this.props;
const { children, wrapperType } = this.props;
// usual case: one child that is a react Element
if (React.isValidElement(children)) {
if (isValidElement(children)) {
return children;

@@ -73,6 +105,14 @@ }

// string children, multiple children, or something else
const childrenArray = Children.toArray(children);
const firstChild = childrenArray[0];
return createElement(wrapperType, {}, ...Children.toArray(children));
}
return createElement(wrapperType, {}, ...childrenArray);
getPollingConfig() {
switch (this.props.polling) {
case true:
return defaultPollingConfig;
case false:
return { enabled: false };
default:
return Object.assign({}, defaultPollingConfig, this.props.polling);
}
}

@@ -101,7 +141,9 @@

startPolling() {
const { interval } = this.getPollingConfig();
this.pollingId = setInterval(() => {
ping(config).then(online => {
const { url, timeout } = this.getPollingConfig();
ping({ url, timeout }).then(online => {
online ? this.goOnline() : this.goOffline();
});
}, config.interval);
}, interval);
}

@@ -112,21 +154,5 @@

}
componentDidMount() {
window.addEventListener("online", this.goOnline);
window.addEventListener("offline", this.goOffline);
if (config.poll) {
this.startPolling();
}
}
componentWillUnmount() {
window.removeEventListener("online", this.goOnline);
window.removeEventListener("offline", this.goOffline);
if (config.poll) {
this.stopPolling();
}
}
}
Base.propTypes = propTypes;
Base.defaultProps = defaultProps;

@@ -138,2 +164,4 @@ export class Online extends Base {

}
Online.propTypes = propTypes;
Online.defaultProps = defaultProps;

@@ -145,2 +173,4 @@ export class Offline extends Base {

}
Offline.propTypes = propTypes;
Offline.defaultProps = defaultProps;

@@ -152,1 +182,5 @@ export class Detector extends Base {

}
Detector.propTypes = Object.assign({}, propTypes, {
render: PropTypes.func.isRequired
});
Detector.defaultProps = defaultProps;

@@ -34,2 +34,12 @@ import React from "react";

it("should render children when online and using a custom polling URL", () => {
const wrapper = mount(
<Online pollingUrl="https://www.google.com/">
<h1>Hello World</h1>
</Online>
);
expect(toJSON(wrapper)).toMatchSnapshot();
});
it("should not render children when offline", () => {

@@ -47,2 +57,14 @@ Object.defineProperty(navigator, "onLine", { value: false });

it("should not render children when offline and using a custom polling URL", () => {
Object.defineProperty(navigator, "onLine", { value: false });
const wrapper = mount(
<Online pollingUrl="https://www.google.com/">
<h1>Hello World</h1>
</Online>
);
expect(wrapper.html()).toBeNull();
});
it("should not render children when going from online to offline", () => {

@@ -91,2 +113,12 @@ const wrapper = mount(

it("should render children when offline and using a custom polling URL", () => {
const wrapper = mount(
<Offline polling={{ url: "https://www.google.com/" }}>
<h1>Hello World</h1>
</Offline>
);
expect(toJSON(wrapper)).toMatchSnapshot();
});
it("should not render children when online", () => {

@@ -104,2 +136,14 @@ Object.defineProperty(navigator, "onLine", { value: true });

it("should not render children when online and using a custom polling URL", () => {
Object.defineProperty(navigator, "onLine", { value: true });
const wrapper = mount(
<Offline polling={{ url: "https://www.google.com/" }}>
<h1>Hello World</h1>
</Offline>
);
expect(wrapper.html()).toBeNull();
});
it("should not render children when going from offline to online", () => {

@@ -106,0 +150,0 @@ const wrapper = mount(

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc