Search code examples
reactjsionic-frameworkcapacitorionic-react

<IonToast> should be shown when there's no network connection, but it's not


I'm working on an Ionic React Project running on top of Capacitor and I need to show a Toast message <IonToast>, everytime there's no internet connection. To get network and connectivity information, I'm using Network Capacitor Plugin: https://capacitorjs.com/docs/apis/network I'm using Context hook for using props everywhere in the app.

In MyContext.tsx I have declared the necessary constants as following:

const [showToast, setShowToast] = useState<boolean>(false);
  const [toastMessage, setToastMessage] = useState("");

In HomePage.tsx:

import {
  IonContent,
  IonPage,
  IonButton,
  IonGrid,
  IonRow,
  IonCol,
  IonAlert,
  IonToast,
} from "@ionic/react";
import React, { useState, useEffect, useRef } from "react";
import { Network } from "@capacitor/network";

const HomePage: React.FC = () => {
  const {
    firstName,
    setFirstName,
    showToast,
    setShowToast,
    toastMessage,
    setToastMessage,
  } = React.useContext(MyContext);
  const history = useHistory();
  const mounted = useRef(true);

  //Check internet connection status
  useEffect(() => {
    mounted.current = true;
    const logCurrentNetworkStatus = async () => {
      const status = await Network.getStatus();
      if (mounted.current) {
        if (status.connected) {
          setShowToast(false);
        } else {
          setShowToast(true);
          setToastMessage("No internet connection");
        }
      }
    };
    return () => {
      logCurrentNetworkStatus();
      mounted.current = false;
    };
  }, []);

  console.log("showToast is " + showToast);
  console.log("Toast message is " + toastMessage);


  return (
    <React.Fragment>
      <IonPage className="ion-page" id="main-content">
        <IonContent className="ion-padding">
          <IonGrid>
            <IonRow>
              <IonCol>
                <IonToast
                  isOpen={showToast}
                  onDidDismiss={() => setShowToast(false)}
                  message={toastMessage}
                  position="top"
                  buttons={["Ok"]}
                />
              </IonCol>
            </IonRow>

                  <h5 className="text-center">Welcome to home page</h5>
                
          </IonGrid>
        </IonContent>
      </IonPage>
    </React.Fragment>
  );
};

export default HomePage;

My issue is: Toast message is not showing at all. I have logged showToast and its value is always false, even when I have no internet connection in my Android emulator (showToast should be set to true).

In console, I can see the result of Network.getStatus:

result Network.getStatus
connected: false

It seems like useEffect() is not executed at all. I added some console.log inside useEffect() and none of them was shown in console when HomePage was rendered. Do you have any idea why?

Any help would be really appreciated! Thank you!


Solution

  • I would suggest moving the network check into MyContext.tsx and use the listener provided by the API

    const [showToast, setShowToast] = useState<boolean>(false);
    const [toastMessage, setToastMessage] = useState("");
    
    
    Network.addListener('networkStatusChange', status => {
      console.log('Network status changed', status);
      status.connected ?  setShowToast(true) :   setShowToast(false)
    });
    

    this way you can set the state appropriate independent of the specific page, which in this example is the home page.