Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect network connection in React Redux app - if offline, hide component from user

I am using google's autocomplete API to improve address input in my form.

I am using GoogleMapsLoader loader which dispatches action once loaded:

GoogleMapsLoader.onLoad(function() {
    store.dispatch(GoogleActions.loaded());
});

In React component I have following input:

if (google.status === 'LOADED') {
    inputGoogle = <div>
        <label htmlFor={`${group}.google`}>Auto Complete:</label>
        <input ref={(el) => this.loadAutocomplete(el)} type="text" />
    </div>;
} else {
    inputGoogle = '';
}

the loadAutocomplete method (not sure if it is best way of doing that) :

loadAutocomplete(ref) {
    if (!this.autocomplete) {
        this.search = ref;
        this.autocomplete = new google.maps.places.Autocomplete(ref);
        this.autocomplete.addListener('place_changed', this.onSelected);
    }
},

UPDATE:

Using answer below I did following:

const GoogleReducer = (state = initialState, action) => {
    switch (action.type) {
        case 'GOOGLE_LOADED':
            return Object.assign({}, state, {
                status: 'LOADED',
                connection: 'ONLINE'
            });
        case 'GOOGLE_OFFLINE':
            return Object.assign({}, state, {
                connection: 'OFFLINE'
            });
        case 'GOOGLE_ONLINE':
            return Object.assign({}, state, {
                connection: 'ONLINE'
            });
        default:
            return state;
    }
};

const GoogleActions = {
    loaded: () => {
        return (dispatch) => {
            dispatch({
                type: 'GOOGLE_LOADED',
            });
        };
    },
    onOnline: () => {
        return (dispatch) => {
            window.addEventListener('online', function() {
                dispatch({
                    type: 'GOOGLE_ONLINE'
                });
            });
        };
    },
    onOffline: () => {
        return (dispatch) => {
            window.addEventListener('offline', function() {
                dispatch({
                    type: 'GOOGLE_OFFLINE'
                });
            });
        };
    }
};

Inside React component:

if (google.status === 'LOADED' && google.connection === 'ONLINE') {
    inputGoogle = <div>
        <label htmlFor={`${group}.google`}>Auto Complete:</label>
        <input ref={(el) => this.loadAutocomplete(el)} name={`${group}.google`} id={`${group}.google`} type="text" onFocus={this.clearSearch}/>
    </div>;
} else {
    inputGoogle = <p>Auto Complete not available</p>;
}

So far works.

like image 558
TheFullResolution Avatar asked Oct 25 '16 19:10

TheFullResolution


6 Answers

you can use the onLine method of the Navigator object, returns a boolean, true if online, then just add a statement in your react render.

https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine

render(){
    var input = navigator.onLine ? <YOUR_FORM_COMPONENT> : null;
    return(
    <div>
        {input}
    </div>
    )    
}
like image 102
StackOverMySoul Avatar answered Oct 09 '22 16:10

StackOverMySoul


I have been using react-detect-offline to handle displaying online/offline specific content, it handles older browsers who do not support the online event with polling and you can specify the polling URL in the options.

https://github.com/chrisbolin/react-detect-offline

First install the package

npm install react-detect-offline

Then in your component you would do something like

import { Offline, Online } from "react-detect-offline"

const MyComponent = () => {
    return (
        <div>
            <Offline>You're offline right now. Check your connection.</Offline>
            <Online>You're online right now.</Online>
        </div>
    );
}
like image 27
Josh Avatar answered Oct 09 '22 16:10

Josh


navigator.onLine will return the status whether it is online or offline but it wont check internet connectivity is there or not. Adding bit more to @StackOverMySoul. To get rid of this can refer below example.

    var condition = navigator.onLine ? 'online' : 'offline';
    if (condition === 'online') {
      console.log('ONLINE');
        fetch('https://www.google.com/', { // Check for internet connectivity
            mode: 'no-cors',
            })
        .then(() => {
            console.log('CONNECTED TO INTERNET');
        }).catch(() => {
           console.log('INTERNET CONNECTIVITY ISSUE');
        }  )

    }else{
       console.log('OFFLINE')
    }

Why choose google.com?

The reason behind sending the get request to google.com instead of any random platform is because it has great uptime. The idea here is to always send the request to a service that is always online. If you have a server, you could create a dedicated route that can replace the google.com domain but you have to be sure that it has an amazing uptime.

like image 31
Maheshvirus Avatar answered Oct 09 '22 16:10

Maheshvirus


Use navigator.onLine to check network connectivity. It return true if network connection is available else return false.

Also try to use navigator.connection to verify network connection status.

var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
    if (connection) {
      if (connection.effectiveType === 'slow-2g')
        preloadVideo = false;
    }

For more Network Information API

like image 28
Codemaker Avatar answered Oct 09 '22 14:10

Codemaker


For react or typescript coders: this guy has simple and reusable solution for it https://medium.com/@vivekjoy/usenetwork-create-a-custom-react-hook-to-detect-online-and-offline-network-status-and-get-network-4a2e12c7e58b

Works for me well.

like image 45
Erik P_yan Avatar answered Oct 09 '22 14:10

Erik P_yan


You can create a custom hook and try to send requests each five seconds:

import { useState, useEffect } from 'react';

const useNetworkStatus = () => {
  const [isOnline, setIsOnline] = useState(true);

  useEffect(() => {
    const interval = setInterval(() => {
      fetch('https://www.google.com/', {
        mode: 'no-cors',
      })
        .then(() => !isOnline && setIsOnline(true))
        .catch(() => isOnline && setIsOnline(false));
    }, 5000);

    return () => clearInterval(interval);
  }, [isOnline]);

  return { isOnline };
};

export default useNetworkStatus;

And then use it like this:

import useNetworkStatus from '@/hooks/useNetworkStatus';
// ...
const { isOnline } = useNetworkStatus();
like image 31
Tarek Hammami Avatar answered Oct 09 '22 15:10

Tarek Hammami