React Hooks Personnalisés : useNetworkState

React Hooks Personnalisés : useNetworkState

·

4 min read

Après avoir implémenté le Hook useLocalStorage pour faciliter la gestion du stockage local, implémentons le Hook useNetworkState pour connaître l'état du réseau de l'utilisateur (savoir s'il est connecté à internet ou non).

Motivation

Supposons que nous soyons en train de développer une application qui nécessite d'être connecté à internet en permanence pour fonctionner convenablement. Si l'utilisateur se retrouve déconnecté, un message doit être affiché, lui informant de vérifier sa connectivité. Pour ce faire, dans une application React, voici comment nous pourrions procéder.

const App = () => {
  const [isOnline, setIsOnline] = useState(window.navigator.onLine);

  useEffect(() => {
    const handleOnline = () => setIsOnline(true);
    const handleOffline = () => setIsOnline(false);

    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);

    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return (
    <div>
      <h1>My Awesome App</h1>
      <p>
        Lorem, ipsum dolor sit amet consectetur adipisicing elit. Culpa
        provident tenetur molestias fugiat expedita quaerat dolores dignissimos
        dicta, error amet reiciendis voluptates delectus perspiciatis dolorum
        saepe, sunt, similique vitae illo.
      </p>
      {!isOnline && (
        <div className="toast">
          You are offline. Please check your connectivity and try again.
        </div>
      )}
    </div>
  );
};

Ceci fonctionne parfaitement. En revanche, notre code pourrait considérablement être simplifié, notamment le Hook useEffect. Notre but est donc de définir un Hook useNetworkState afin d'abstraire cette logique dans un Hook séparé. Cela permettra à la fois de simplifier notre composant, mais aussi (et surtout) de pouvoir réutiliser cette logique à d'autres endroits de notre application sans dupliquer de code. Maintenant que nous savons pourquoi nous avons besoin de ce Hook, passons à l'implémentation. 👨🏻‍💻

Implémentation

Comme à notre habitude, réfléchissons d'abord à l'interface de notre Hook afin de savoir comment nous allons l'utiliser. Dans notre cas, nous voudrions quelque chose d'aussi simple que ça :

const isOnline = useNetworkState()

Ni plus, ni moins. Il nous retournerait une simple valeur booléenne qui sera mise à jour automatiquement et convenablement pour se synchroniser avec l'état actuel de la connectivité de l'utilisateur.

Nous pouvons donc passer à l'implémentation, qui consistera tout simplement en l'extraction de la logique que nous avons écrite précédemment au sein d'une fonction séparée. Le Hook final n'est donc pas plus compliqué que ça :

const useNetworkState = () => {
  const [isOnline, setIsOnline] = useBoolean(window.navigator.onLine);

  useEffect(() => {
    window.addEventListener('online', setIsOnline.on);
    window.addEventListener('offline', setIsOnline.off);

    return () => {
      window.removeEventListener('online', setIsOnline.on);
      window.removeEventListener('offline', setIsOnline.off);
    };
  }, []);

  return isOnline;
};

Euh, c'est quoi ce Hook useBoolean ? 🤨

Effectivement, il n'est pas fourni directement par React. Cependant, pour ceux qui suivraient cette série depuis le tout début, ce Hook devrait vous rappeler quelque chose : c'est le tout premier Hook personnalisé que nous avons implémenté ensemble !

Si vous avez découvert cette série en cours de route, pas d'inquiétude : je vous invite à lire cet article pour en apprendre plus sur ce Hook.

Si vous ne souhaitez pas utiliser le Hook useBoolean, vous pouvez vous contenter d'un simple useState.

const useNetworkState = () => {
  const [isOnline, setIsOnline] = useState(window.navigator.onLine);

  useEffect(() => {
    const handleOnline = () => setIsOnline(true);
    const handleOffline = () => setIsOnline(false);

    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);

    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return isOnline;
};

Utilisation

Si nous reprenons notre composant App de tout à l'heure, voici comment il peut être simplifié grâce à notre tout nouveau Hook :

const App = () => {
  const isOnline = useNetworkState()

  return (
    <div>
      <h1>My Awesome App</h1>
      <p>
        Lorem, ipsum dolor sit amet consectetur adipisicing elit. Culpa
        provident tenetur molestias fugiat expedita quaerat dolores dignissimos
        dicta, error amet reiciendis voluptates delectus perspiciatis dolorum
        saepe, sunt, similique vitae illo.
      </p>
      {!isOnline && (
        <div className="toast">
          You are offline. Please check your connectivity and try again.
        </div>
      )}
    </div>
  );
};

Eh oui, je vous l'avais dit, notre code est désormais bien plus simple ! 😎

Conclusion

Nous avons réussi à abstraire toute la logique de connectivité réseau à l'extérieur de notre composant, qui se concentre maintenant sur ce qu'il doit réellement faire. Grâce à cela, nous suivons le principe de séparation des préoccupations, ou Separation of Concerns en anglais (SOC). Vous trouverez plus d'informations sur ce lien. Dans le prochain article, nous allons implémenter un Hook pour utiliser plus facilement les effets sonores : useAudio.


Code source disponible sur CodeSandbox.

Did you find this article valuable?

Support Ludal by becoming a sponsor. Any amount is appreciated!