Home > Blockchain >  How to collect and return multiple functions from a custom hook
How to collect and return multiple functions from a custom hook

Time:07-04

Main.tsx:

import React from "react";
import { useRectangleControls } from "src/useRectangleControls";

export function Main() {
    const rectangleRef = React.useRef<HTMLDivElement>(null);
    const mainControls = useRectangleControls(rectangleRef);

    React.useEffect(() => {
        console.log(mainControls.isMouseInRectangle);
    }, [mainControls.isMouseInRectangle]);

    return (
        <div className="w-full h-screen flex items-center justify-center">
            <div className="w-[60%] h-[30%] bg-green-900" ref={rectangleRef} onm ouseEnter={mainControls.onMouseEnter} onm ouseLeave={mainControls.onMouseLeave}></div>
        </div>
    );
}

The above component returns a rectangle. The color of the rectangle depends on the mouse position. The event handlers for onMouseEnter and onMouseLeave were shifted to a custom hook called useRectangleControls:

import React from "react";

export function useRectangleControls(rectangleRef: React.RefObject<HTMLDivElement>) {
    const [isMouseInRectangle, setIsMouseInRectangle] = React.useState(false);

    function onm ouseEnter() {
        if (rectangleRef.current) {
            setIsMouseInRectangle(true);
            rectangleRef.current.classList.remove("bg-green-900");
            rectangleRef.current.classList.add("bg-red-900");
        }
    }
    function onm ouseLeave() {
        if (rectangleRef.current) {
            setIsMouseInRectangle(false);
            rectangleRef.current.classList.remove("bg-red-900");
            rectangleRef.current.classList.add("bg-green-900");
        }
    }


    return { onm ouseEnter, onm ouseLeave, isMouseInRectangle };
}

I want to collect all functions and return them in one variable. I want the return statement to look something like this: return {rectangleControls, isMouseInRectangle} where rectangleControls contains all functions inside the useRectangleControls custom hook.

My goal is to avoid updating the return statement each time I add a new function to useRectangleControls

CodePudding user response:

You can do that in the following way

    import React from "react";
    
    export interface Indexable<T = any> {
      [key: string]: T|undefined;
    }
     export interface RectangleControls {
          onm ouseEnter: () => void;
          onm ouseLeave: () => void;
      }
            
            export function useRectangleControls(rectangleRef: React.RefObject<HTMLDivElement>) {
                const [isMouseInRectangle, setIsMouseInRectangle] = React.useState(false);
//           const rectangleControls: Indexable = {}; // one approach for typescript
const rectangleControls: RectangleControls = {
   onm ouseEnter: () => {},
   onm ouseLeave: () => {}
}; // second approach for typescript
         
            
                 rectangleControls.onMouseEnter = () => {
                    if (rectangleRef.current) {
                        setIsMouseInRectangle(true);
                        rectangleRef.current.classList.remove("bg-green-900");
                        rectangleRef.current.classList.add("bg-red-900");
                    }
                }
                rectangleControls.onMouseLeave = () => {
                    if (rectangleRef.current) {
                        setIsMouseInRectangle(false);
                        rectangleRef.current.classList.remove("bg-red-900");
                        rectangleRef.current.classList.add("bg-green-900");
                    }
                }
            
            
                return { rectangleControls, isMouseInRectangle };
            }

Edit: Explaining the changes made in the hook. Here I have created an Object rectangleControls and converted the onm ouseEnter, onm ouseLeave to arrow function and assign them as key to rectangleControls, this will help you achieve what you are looking for exporting a single variable.

CodePudding user response:

You will just need to import your custom hook useRectangleControls inside the component where you're going to use it. then use the onMouseEnter, onm ouseLeave, isMouseInRectangle from it like so.

const { onm ouseEnter, onm ouseLeave, isMouseInRectangle } = useRectangleControls(pass your params here);

don't forget to import it from its location.

for example:

import useRectangleControls from "./hooks/useRectangleControls";

That's it.

  • Related