♼ Writing re-usable logic with React HooksMay 27, 2021JavaScript 314 words

React developers who have used functional components are usually familiar with useEffect() and useState(). These called Hooks, They let you use state and other React features without writing a class.

You can implement your own custom Hook that can be re-used in your application or by others. Let me show how with an example application which is able to detect whether your device is online or offline.

A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks.

import React, { useEffect } from 'react';
 
const App = () => {
  const [isOnline, setIsOnline] = React.useState();
 
  const offline = () => setIsOnline(false);
  const online = () => setIsOnline(true);
  
  useEffect(() => {
    window.addEventListener('offline', offline);
    window.addEventListener('online', online);
 
    return () => {
      window.removeEventListener('offline', offline);
      window.removeEventListener('online', online);
    };
  }, []);
 
  if (!isOnline) {
    return <div>Sorry, you are offline ...</div>;
  }
 
  return <div>You are online!</div>;
}
 
export default App;

the useEffect() adds and removes listeners that check if the device is online or offline. Both listeners are setup only once on mount and cleaned up once on unmount (empty array as second argument). Whenever one of the listeners is called, it sets the state in isOnline.

What if we want to re-use this logic in multiple components or applications? It’s just simply a matter of extracting the core logic to another function. We prefix this function with use to let others know at a glance that the rules of Hooks apply to it.

import React, { useEffect } from 'react';

const useOnline = () => {
const [isOnline, setIsOnline] = React.useState();
 
  const offline = () => setIsOnline(false);
  const online = () => setIsOnline(true);
  
  useEffect(() => {
    window.addEventListener('offline', offline);
    window.addEventListener('online', online);
 
    return () => {
      window.removeEventListener('offline', offline);
      window.removeEventListener('online', online);
    };
  }, []);
  
  return isOnline;
}

There’s nothing new here — the logic is copied from the component above. Our goal was to able to re-use the logic to check if device is online or offline, and now that we have extracted this logic to a useOnline hook, we can use it like:

import React from 'react';
import { useOnline } from './hooks';
 
const App = () => {
	const isOnline = useOnline();
	
	if (!isOnline) {
    return <div>Sorry, you are offline ...</div>;
  }
 
  return <div>You are online!</div>;
}
 
export default App;
	

Is this code equivalent to the original examples? Yep, it works in exactly the same way, since we didn’t make any changes to the behavior. All we did was to extract a core logic into a separate function.

Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.

That’s it for the custom hook that detects whether you are online or offline. You can read more about custom hooks in React’s documentation.

If you want to look at more complex usages of custom hooks, checkout useHooks(🐠) by ui.dev