Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ref issue and Calling custom hook after useEffect

I am using a custom hook to detect outside clicks

const useClickOutside = (nodeElement, handler) => {

    function handleClickOutside(event) {
        if (nodeElement && !nodeElement.contains(event.target)) {
            handler();
        }
    }

    useEffect(() => {
        document.addEventListener('mousedown', handleClickOutside);
        return () =>  document.removeEventListener('mousedown', handleClickOutside);
    }, []);  
} 

And I am calling it like this

const Modal = ({ ... }) => {

    const modalRef = useRef(null);

    console.log(modalRef.current) // null

    useEffect(() => {
        console.log(modalRef.current) // work fine here and display the dom element
    }, [])

    // here the hooks it is called with modalRef.current as null
    useClickOutside(modalRef.current, () => { 
        dispatch(hideModal());
    });

    return (
        <div className="pop-container">
            <div className="pop-dialog" ref={modalRef}>
                ...
            </div>
        </div>
    )
}

The problem is that my custom hooks useClickOutside is called with modalRef.current as null

And as you see in the useEffet hook the modalRef.current value is correct

However i can't call my custom hook there in useEffet otherwise i will get Uncaught Invariant Violation: Hooks can only be called inside the body of a function component

So how to solve this issue ?

like image 854
Hayi Avatar asked Dec 06 '25 06:12

Hayi


1 Answers

Instead of passing ref.current, if you just pass ref, your code will work since ref.current will be mutated at its reference when ref is assigned

const useClickOutside = (nodeElement, handler) => {

    function handleClickOutside(event) {
        if (nodeElement.current && !nodeElement.current.contains(event.target)) {
            handler();
        }
    }

    useEffect(() => {
        document.addEventListener('mousedown', handleClickOutside);
        return () =>  document.removeEventListener('mousedown', handleClickOutside);
    }, []);  
} 

and in modal

const Modal = ({ ... }) => {

    const modalRef = useRef(null);

    // here the hooks it is called with modalRef.current as null
    useClickOutside(modalRef, () => { 
        dispatch(hideModal());
    });

    return (
        <div className="pop-container">
            <div className="pop-dialog" ref={modalRef}>
                ...
            </div>
        </div>
    )
}

Working demo

like image 79
Shubham Khatri Avatar answered Dec 08 '25 20:12

Shubham Khatri



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!