DEV Community

Cover image for How to create a custom Hook in React with typescript?
Ritik Banger
Ritik Banger

Posted on

How to create a custom Hook in React with typescript?

Typescript usage is growing day-by-day as many web developers are shifting to use React.js for solving custom requirements. With the introduction of react hooks in functional components, it becomes easier to develop more complex solutions for the real-world problems.

React hooks are basically functions that let you “hook into” React state and lifecycle features from function components, and thus help us in solving problems using functional components rather than class components, which is more complex and confusing.

Creating custom hooks are the new industry practice and still many react developers find it

So, here in this tutorial, I will make you understand what custom hooks are and how we can implement them in our own way. Here are a few points to keep in mind.

  1. Custom hooks are basically functions that may or may not need some arguments and return something to the caller component.

  2. Custom hooks name starts with the word use so that react identify it as a hook, otherwise your hook will act just as a normal function or component doing some task and returning something.

  3. Hooks make your code more flexible and you do not need to write a solution again and again in different components and invoking those solutions.

Now, I am creating a hook to find the render count of a component. In this we are using useRef hook to use its current property.

import React, { useRef } from 'react';

const SHOW_RENDER_COUNTERS = true;

export const useRenderCounter = (): number | null => {
  const renderCount = useRef(0);
  renderCount.current = renderCount.current + 1;

  if (SHOW_RENDER_COUNTERS) {
    return renderCount.current
  }
  return null;
};
Enter fullscreen mode Exit fullscreen mode

Now, whenever we wish to use this hook to find the render count we can use it like this:

const FindCount = () => {
  const renderCounter = useRenderCounter();

  return (
    <>
      <SomeComponentCode />
      {renderCounter}
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

This is how we can create and use custom hooks.

Some other examples of custom hooks are:

1. Hook to Show tooltip when a user clicks on something.

import { useState, useRef, useEffect } from 'react'

export const useTooltip = (initialState: boolean) => {
  const ref = useRef<HTMLDivElement>(null)
  const [showTooltip, setShowTooltip] = useState<boolean>(initialState)

  const handleClick = (event: any) => {
    if (ref.current && !ref.current.contains(event.target)) {
      setShowTooltip(false)
    }
  }

  useEffect(() => {
    document.addEventListener('click', handleClick, true)

    return () => document.removeEventListener('click', handleClick, true)
  }, [ref])

  return { showTooltip, setShowTooltip, ref }
}

Enter fullscreen mode Exit fullscreen mode

2. Hook to get the screen height.

import { useState, useEffect, useRef, RefObject } from 'react'

interface InterfaceSize {
  size: number
  sizeRef: RefObject<HTMLDivElement>
}
const useSize = (initialValue: number): InterfaceSize => {
  const sizeRef = useRef<HTMLDivElement>(null)
  const [size, setSize] = useState<number>(initialValue)

  useEffect(() => {
    setTimeout(() => {
      if (sizeRef.current) {
        setSize(sizeRef.current?.getBoundingClientRect().height)
      }
    }, 100)
  }, [size])

  return { size, sizeRef }
}

export default useSize

Enter fullscreen mode Exit fullscreen mode

3. Hook that give alert when clicks outside of the passed ref.

import React, { useRef, useEffect } from "react";

/**
 * Hook that alerts clicks outside of the passed ref
 */
function useOutsideAlerter(ref: React.RefObject<HTMLInputElement>) {
  useEffect(() => {
    /**
     * Alert if clicked on outside of element
     */
    function handleClickOutside(event: Event) {
      if (ref.current && !ref.current.contains(event.target as Node))) {
        alert("You clicked outside of me!");
      }
    }
    // Bind the event listener
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      // Unbind the event listener on clean up
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [ref]);
}

/**
 * Component that alerts if you click outside of it
 */
export default function OutsideAlerter(props) {
  const wrapperRef = useRef(null);
  useOutsideAlerter(wrapperRef);

  return <div ref={wrapperRef}>{props.children}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
ritikbanger profile image
Ritik Banger

Thankyou @lukeshiru for the thoughts.