Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to collect and return multiple functions from a custom hook

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} onMouseEnter={mainControls.onMouseEnter} onMouseLeave={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 onMouseEnter() {
        if (rectangleRef.current) {
            setIsMouseInRectangle(true);
            rectangleRef.current.classList.remove("bg-green-900");
            rectangleRef.current.classList.add("bg-red-900");
        }
    }
    function onMouseLeave() {
        if (rectangleRef.current) {
            setIsMouseInRectangle(false);
            rectangleRef.current.classList.remove("bg-red-900");
            rectangleRef.current.classList.add("bg-green-900");
        }
    }


    return { onMouseEnter, onMouseLeave, 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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

>Solution :

You can do that in the following way

    import React from "react";
    
    export interface Indexable<T = any> {
      [key: string]: T|undefined;
    }
     export interface RectangleControls {
          onMouseEnter: () => void;
          onMouseLeave: () => void;
      }
            
            export function useRectangleControls(rectangleRef: React.RefObject<HTMLDivElement>) {
                const [isMouseInRectangle, setIsMouseInRectangle] = React.useState(false);
//           const rectangleControls: Indexable = {}; // one approach for typescript
const rectangleControls: RectangleControls = {
   onMouseEnter: () => {},
   onMouseLeave: () => {}
}; // 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 onMouseEnter, onMouseLeave to arrow function and assign them as key to rectangleControls, this will help you achieve what you are looking for exporting a single variable.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading