Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React from "react";
- import ReactDOM from "react-dom";
- class OnlineStatusEventDispatcher {
- constructor() {
- this.timer;
- this.initialStatus;
- this.wasOnlineLastTime;
- this.isDispatcherCalledForFirstTime = true;
- this.setupFetchConf = this.setupFetchConf.bind(this);
- this.checkOnlineStatus = this.checkOnlineStatus.bind(this);
- this.handleDispatching = this.handleDispatching.bind(this);
- this.initDispatcher = this.initDispatcher.bind(this);
- this.cancelDispatcher = this.cancelDispatcher.bind(this);
- this.setInitialStatus = this.setInitialStatus.bind(this);
- this.setConf = this.setConf.bind(this);
- this.onLineEvent = new CustomEvent('isOnlineFallback', {
- detail: {
- onLine: true
- }
- });
- this.offLineEvent = new CustomEvent('isOnlineFallback', {
- detail: {
- onLine: false
- }
- });
- this.setupFetchConf();
- }
- setConf(conf) {
- this.conf = conf;
- }
- setInitialStatus(status) {
- this.initialStatus = status;
- }
- setupFetchConf() {
- const headers = new Headers();
- headers.append('pragma', 'no-cache');
- headers.append('cache-control', 'no-cache');
- this.fetchConf = {
- method: 'GET',
- headers: headers,
- };
- }
- async checkOnlineStatus(path = '') {
- const timeout = new Promise((resolve, reject) => {
- setTimeout(reject, this.conf.timeoutInterval ? this.conf.timeoutInterval : 3000);
- });
- let isOnline = true;
- await Promise.race([
- fetch(`/${path}`, this.fetchConf),
- timeout
- ])
- .then(() => (isOnline = true))
- .catch(() => (isOnline = false));
- return isOnline;
- }
- async handleDispatching() {
- const isOnline = await this.checkOnlineStatus(this.conf.serverResourcePath);
- if (this.isDispatcherCalledForFirstTime && this.initialStatus === isOnline) {
- this.isDispatcherCalledForFirstTime = false;
- if (this.initialStatus) {
- this.wasOnlineLastTime = true;
- }
- return;
- }
- if (isOnline && !this.wasOnlineLastTime) {
- window.dispatchEvent(this.onLineEvent);
- this.wasOnlineLastTime = true;
- } else if (!isOnline && this.wasOnlineLastTime) {
- window.dispatchEvent(this.offLineEvent);
- this.wasOnlineLastTime = false;
- }
- }
- initDispatcher(interval = 6000) {
- this.timer = window.setInterval(this.handleDispatching, interval);
- }
- cancelDispatcher() {
- this.timer.clearInterval();
- }
- }
- //singleton
- const dispatcherInstance = new OnlineStatusEventDispatcher();
- const withNetworkInfo = (conf) => (Component) => {
- return class extends React.Component {
- constructor() {
- super();
- this.state = {
- isConnectionSupported: false,
- isOnline: true,
- networkInfo: null,
- }
- this._validateConf(conf);
- if (conf.enableCustomOnlineStatusChecking) {
- this.onlineStatusEventDispatcher = dispatcherInstance;
- this.onlineStatusEventDispatcher.setConf(conf);
- }
- }
- componentWillMount() {
- if (conf.enableCustomOnlineStatusChecking) {
- this._setInitialOnlineStatus()
- .then(status => {
- this.setState({
- isOnline: status
- });
- this.onlineStatusEventDispatcher.setInitialStatus(status);
- this.onlineStatusEventDispatcher.initDispatcher(conf.offlineRequestsInterval);
- });
- } else {
- this.setState({
- isOnline: navigator.onLine
- });
- }
- if ('connection' in navigator) {
- this.setState({
- isConnectionSupported: true,
- networkInfo: navigator.connection
- });
- }
- }
- componentDidMount() {
- if (conf.enableCustomOnlineStatusChecking) {
- window.addEventListener('isOnlineFallback', this._onlineStatusFallbackChange.bind(this));
- } else {
- window.addEventListener('online', this._onOnlineStatusChange.bind(this));
- window.addEventListener('offline', this._onOnlineStatusChange.bind(this));
- }
- this.state.isConnectionSupported && navigator.connection.addEventListener('change', this._onConnectionChange.bind(this));
- }
- componentWillUnmount() {
- if (conf.enableCustomOnlineStatusChecking) {
- window.removeEventListener('isOnlineFallback', this._onlineStatusFallbackChange.bind(this));
- this.onlineStatusEventDispatcher.cancelDispatcher();
- } else {
- window.removeEventListener('online', this._onOnlineStatusChange.bind(this));
- window.removeEventListener('offline', this._onOnlineStatusChange.bind(this));
- }
- this.state.isConnectionSupported && navigator.connection.removeEventListener('change', this._onConnectionChange.bind(this));
- }
- _validateConf(conf) {
- if (conf.timeoutInterval >= conf.offlineRequestsInterval) {
- throw Error('timeoutInteval param must not exceed offlineRequestInterval param value.');
- }
- }
- async _setInitialOnlineStatus() {
- const isOnline = await this.onlineStatusEventDispatcher.checkOnlineStatus();
- return isOnline;
- }
- _onOnlineStatusChange() {
- this.setState({
- isOnline: navigator.onLine
- });
- }
- _onlineStatusFallbackChange(event) {
- console.log('EVENT', event.detail);
- this.setState({
- isOnline: event.detail.onLine
- })
- }
- _onConnectionChange() {
- this.setState({
- networkInfo: navigator.connection
- });
- }
- render() {
- return (
- <Component
- networkInfo={this.state.networkInfo}
- isOnline={this.state.isOnline}
- {...this.props} />
- );
- }
- }
- }
- class InfoLogger extends React.Component {
- constructor() {
- super();
- }
- render() {
- return (
- <span>{this.props.networkInfo.effectiveType} / {this.props.isOnline ? 'online' : 'offline'}</span>
- );
- }
- }
- const InfoLoggerExample = withNetworkInfo({
- enableCustomOnlineStatusChecking: true,
- serverResourcePath: 'favicon.ico',
- offlineRequestsInterval: 5000,
- timeoutInterval: 3000
- })(InfoLogger);
- class Application extends React.Component {
- render() {
- return <div>
- <h1>{<InfoLoggerExample />}</h1>
- </div>;
- }
- }
- ReactDOM.render(<Application />, document.getElementById('app'));
Add Comment
Please, Sign In to add comment