Live Chat Icon For mobile
Live Chat Icon
Popular Categories.NET  (157).NET Core  (28).NET MAUI  (36)Angular  (65)ASP.NET  (48)ASP.NET Core  (73)ASP.NET MVC  (88)Azure  (31)Blazor  (134)DocIO  (22)Essential JS 2  (76)Essential Studio  (169)File Formats  (25)Flutter  (121)JavaScript  (167)Microsoft  (109)PDF  (64)React  (47)Succinctly series  (126)Syncfusion  (550)TypeScript  (30)Uno Platform  (3)UWP  (4)Vue  (34)Webinar  (30)Windows Forms  (57)WinUI  (40)WPF  (131)Xamarin  (148)XlsIO  (25)Other CategoriesBarcode  (5)BI  (29)Bold BI  (4)Build conference  (6)Business intelligence  (53)Button  (4)C#  (115)Chart  (56)Cloud  (11)Company  (445)Dashboard  (7)Data Science  (3)Data Validation  (6)DataGrid  (53)Development  (335)Doc  (7)DockingManager  (1)eBook  (95)Enterprise  (22)Entity Framework  (5)Essential Tools  (14)Excel  (22)Extensions  (17)File Manager  (4)Gantt  (11)Gauge  (9)Git  (4)Grid  (27)HTML  (9)Installer  (2)Knockout  (2)Language  (1)LINQPad  (1)Linux  (2)M-Commerce  (1)Metro Studio  (11)Mobile  (277)Mobile MVC  (9)OLAP server  (1)Open source  (1)Orubase  (12)Partners  (21)PDF viewer  (28)Performance  (8)PHP  (1)PivotGrid  (4)Predictive Analytics  (6)Report Server  (3)Reporting  (10)Reporting / Back Office  (11)Rich Text Editor  (7)Road Map  (10)Scheduler  (34)SfDataGrid  (9)Silverlight  (21)Sneak Peek  (21)Solution Services  (2)Spreadsheet  (11)SQL  (8)Stock Chart  (1)Surface  (4)Tablets  (5)Theme  (11)Tips and Tricks  (88)UI  (190)Uncategorized  (68)Unix  (2)User interface  (68)Visual State Manager  (1)Visual Studio  (23)Visual Studio Code  (14)Web  (302)What's new  (179)Windows 8  (19)Windows App  (2)Windows Phone  (15)Windows Phone 7  (9)WinRT  (26)
Share on twitter
Share on facebook
Share on linkedin
Implementing React Custom Hooks: A Complete Guide

Implementing React Custom Hooks: A Complete Guide

React Hooks are functions that allow you to use state and life-cycle features from function components. If you’ve been using React, you’ve probably used their built-in Hooks, such as useState, useEffect, and useContext. However, React does not limit you to using only those Hooks.

Creating your own Hooks in React can be useful in various situations. Custom Hooks are an excellent way to share logic between components and improve your component tree’s readability.

This article explains how to implement various custom Hooks in React. Let’s get started.

Implementing a custom Hook

A custom Hook is a JavaScript function that begins with use. It is not mandatory to begin the custom Hook name with “use,” but without it, React would be unable to check for violations of the Hooks rules automatically. Therefore, it is critical to adhere to that naming convention.

Consider the following example of defining a custom Hook called useFriendStatus.

import { useState, useEffect } from 'react';

function useFriendStatus(friendID) {  
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

In the above example, we call the useState and useEffect Hooks unconditionally at the top level of our custom Hook, just as we would in a component. The useFriendStatus Hook’s purpose is to subscribe us to a friend’s status. As a result, it accepts a friendID as an argument and returns whether the friend is online.

If we didn’t define the useFriendStatus custom Hook, we’d have to write the logic inside this Hook in every component to subscribe to a friend’s status. So, instead of duplicating code, we can use this custom Hook.

Now, let’s look at how we can put this custom Hook to use.

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
export default FriendStatus;
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);
  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}
export default FriendListItem;

In the above example, you can see that the useFriendStatus Hook is used in two different functional components, FriendStatus and FriendListItem. You can even use the same custom Hook twice within the same component.

Note: The state is not shared between two components that use the same Hook.

Passing information between Hooks

Since Hooks are a type of function, we can pass data between them. Consider the following example where a user can select any friend and see whether that friend is online.

const friendList = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Michael' },
  { id: 3, name: 'Mary' },
];

function ChatRecipientPicker() {
  const [recipientID, setRecipientID] = useState(1);  
  const isRecipientOnline = useFriendStatus(recipientID);
  return (
    <>
      <Circle color={isRecipientOnline ? 'green' : 'red'} />
      <select
        value={recipientID}
        onChange={e => setRecipientID(Number(e.target.value))}
      >
        {friendList.map(friend => (
          <option key={friend.id} value={friend.id}>
            {friend.name}
          </option>
        ))}
      </select>
    </>
  );
}

Here, the recipientID state variable value is passed as an argument to the custom useFriendStatus Hook. When the user selects a different friend in the <select> picker, we use the useState Hook to update the recipientID. The useFriendStatus Hook then unsubscribes from the previously selected friend and subscribes to the newly selected friend’s status.

Custom Hooks examples

Now that you have an understanding of how custom Hooks work, let’s look at several scenarios for creating custom Hooks.

useLocalStorage

To use local storage in React, we can construct a custom Hook. The Hook allows you to preserve data in the browser as key-value pairs for later use.

import { useState } from "react";
export default function App() {
  // Usage
  const [name, setName] = useLocalStorage("name", "John");
  return (
    <div>
      <input
        type="text"
        placeholder="Enter your name"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
    </div>
  );
}
// Hook
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.log(error);
      return initialValue;
    }
  });
const setValue = (value) => {
    try {
      const valueToStore =
        value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key,JSON.stringify(valueToStore));
    } catch (error) {
      console.log(error);
    }
  };
  return [storedValue, setValue];
}

useToggle

This is a simple but helpful custom Hook that can be used effectively in many web applications. The useToggle Hook allows you to take a true or false value and convert it to the inverse. It can be used to toggle modals and menus.

import { useCallback, useState } from 'react';
export default function App() {
    // Usage
    const [isModalOpen, setIsModalOpen] = useToggle();
    return (
        <button onClick={setIsModalOpen}>
          {isModalOpen ? 'Close Modal' : 'Open Modal'} 
        </button>
    );
}
// Hook
const useToggle = (initialState = false) => {
    const [state, setState] = useState(initialState);
    const toggle = useCallback(() => setState(state => !state), []);
    return [state, toggle]
}

useEventListener

You may find yourself adding a lot of event listeners using useEffect in your code. In such situations, you should move that logic to a custom Hook. The useEventListener Hook first ensures that the element supports the addEventListener method, and then it creates and adds an event listener. If eventName or element changes, the Hook will rerun.

import { useState, useRef, useEffect, useCallback } from "react";
export default function App() {
  const [coords, setCoords] = useState({ x: 0, y: 0 });
  const handler = useCallback(
    ({ clientX, clientY }) => {
      setCoords({ x: clientX, y: clientY });
    },
    [setCoords]
  );
  // Usage
  useEventListener('mousemove', handler);
return (
    <h1>
      The mouse position is ({coords.x}, {coords.y})
    </h1>
  );
}
// Hook
function useEventListener(eventName, handler, element = window) {
  const savedHandler = useRef();
  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);
  useEffect(
    () => {
      const isSupported = element && element.addEventListener;
      if (!isSupported) return;
      const eventListener = event => savedHandler.current(event);
      element.addEventListener(eventName, eventListener);
      return () => {
        element.removeEventListener(eventName, eventListener);
      };
    },
    [eventName, element]
  );
}

Similarly, you can write custom Hooks to handle various use cases, such as form handling, animation, timers, and many others.

Advantages of custom Hooks

The main advantage of React Hooks is the reusability of stateful logic. In addition, custom Hooks can be easily shared with other components without changing the component hierarchy. Also, we don’t have to be concerned about the this keyword when using Hooks.

Compared to HOCs, the custom Hooks approach provides cleaner logic and a better understanding of the relationship between the data and the component. As a result, it’s easier to read and has fewer lines of code.

We can write separate unit tests for custom Hooks, making testing easier. It is also easier to test components with multiple custom Hooks using the React Testing Library.

Conclusion

Custom Hooks enable exceptional flexibility in sharing logic previously unavailable in React components. I hope this guide has given you a better understanding of creating your own React Hooks.

Thank you for reading.

The Syncfusion React JS suite offers over 65 high-performance, lightweight, modular, and responsive UI components in a single package. This library is the only suite you’ll ever need to construct a complete application.

If you have any questions or comments, you can contact us through our support forumssupport portal, or feedback portal. We are always happy to assist you!

Related blogs

Tags:

Share this post:

Share on twitter
Share on facebook
Share on linkedin
Popular Now

Be the first to get updates

Subscribe RSS feed
Scroll To Top