Home > Net >  check if a user is online and close a modal
check if a user is online and close a modal

Time:09-16

I have a helper function checkOnline, with a function which tests whether my app is online or offline. I then have a component with a modal. I want to update the state of this modal depending on whether the user is online or not. If he is offline I want to make the modal disapear. I am not sure on how to call the function, if the eventlistenner is taken into account. I also do not want to call the function on repeat. Maybe I have to put it in a useEffect. The goal is to run the function depending on wether the addeventlistenner changes from online to offline...

checkOnline.js

export const isOnline = async () => {
    if (!window.navigator.onLine) return false;

    // avoid CORS errors with a request to your own origin
    const url = new URL(window.location.origin);

    // random value to prevent cached responses
    url.searchParams.set('rand', Date.now());
    
    try {
        const response = await fetch(url.toString(), { method: 'HEAD' });

        return response.ok;
    } catch {
        return false;
    }
};

window.addEventListener('online', () => console.log('online'));
window.addEventListener('offline', () => console.log('offline'));

App.js

import { isOnline } from "../../helpers/CheckOnline";

export default function App() {
  const [isModalVisible, setIsModalVisible] = useState(false);

  const modal = async () => {
    const online = await isOnline();
    if (!online) {
      setIsModalVisible(false);
    }
  };

  modal();
  return (
    <div className="App">
      <Modal centered visible={isModalVisible}>
        <p>test</p>
      </Modal>
    </div>
  );
}

CodePudding user response:

You should use the addEventListener and removeEventListener in an useEffect to prevent adding a listener, everytime a rerender happens. A solution therefore might be this one. It's basically the same you already have, with small changes:

import { useCallback, useEffect, useState } from "react";

export const isOnline = async () => {
  if (!window.navigator.onLine) return false;

  // avoid CORS errors with a request to your own origin
  const url = new URL(window.location.origin);

  // random value to prevent cached responses
  url.searchParams.set("rand", Date.now());

  try {
    const response = await fetch(url.toString(), { method: "HEAD" });

    return response.ok;
  } catch {
    return false;
  }
};

// simple indicator whether it works or doesn't
const Modal = ({ visible }) => (visible ? <div>Modal</div> : null);

export default function App() {
  const [isModalVisible, setIsModalVisible] = useState(false);

  const isOnlineHandler = useCallback(async () => {
    const online = await isOnline();

    if (!online) {
      setIsModalVisible(false);
    }
  }, []);

  useEffect(() => {
    window.addEventListener("online", isOnlineHandler);
    return () => {
      window.addEventListener("offline", isOnlineHandler);
    };
  }, [isOnlineHandler]);

  return (
    <div className="App">
      <Modal centered visible={isModalVisible}>
        <p>test</p>
      </Modal>
    </div>
  );
}

To have a working example, I've added a simplified Modal component.

CodePudding user response:

U can use this custom hook. Check if is online / offline with event and navigator.

On sandbox u can test it with offline mode in Chrome

https://codesandbox.io/s/snowy-cherry-z1hlvi

export const useIsOnline = () => {
    const [online, setOnline] = useState(window.navigator.onLine)

    const checkOnline = useCallback(async () => {
        const url = new URL(window.location.origin);

         // random value to prevent cached responses
         url.searchParams.set('rand', Date.now());

         try {
              const response = await fetch(url.toString(), { method: 'HEAD' });                 
              setOnline(response.ok);
         } catch {
              setOnline(false)
         }
    }, [])

    useEffect(() => {
        const offlineCallback = () => setOnline(false)

        window.addEventListener('online', checkOnline);
        window.addEventListener('offline', offlineCallback);

        return () => {
            window.removeEventListener('online', checkOnline)
            window.removeEventListener('offline', offlineCallback)
        }
    }, [checkOnline])

    return online
}
  • Related