Why and how RefObject pass into custom hook automatically?

165 Views Asked by At

I'm using several hooks, which applies + - the same logic of the hook usage. But hook on the target element didn't pass the ref of this element through props(parameters) of this hook.

Simplified hook code:

const useHook = () => {
    const containerRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        if (!containerRef.current) throw new Error('container is not defined'); 
        console.log(containerRef.current) // => and here we will have a reference to the element. Why?
        
        /*some logic*/
    }, []);

    return containerRef;
}

Usage of this hook:

export const TestComponent = () => {
    const hookRef = useHook();

    return <div ref={hookRef}>/*smth else*/</div>
}

Why we create ref, like const hookRef = useHook()?

I'm used to use eventListeners in js like that:

function handler(event) {}
element.addEventListener("click", handler)

In the abovementioned code with event listener we pass event into callback automatically, right? We also can write following code and the results will be the same(on a cursory examination):

function handler(event) {}
element.addEventListener("click", (event) => handler(event))

Right.
But if we were able to do this, then we can do that:

export const TestComponent = () => {
    const hookRef = useHook();

    return <div ref={el => hookRef(el)}>/*smth else*/</div>
}

But no.. We can't. (Yes, I understand, that in the hook function we have no parameters, but, again, how this ref pass into the hook?).

What I need to know to understand this hook/useRef logic? Will be glad to every your answear, thanks a lot.

EDIT
But what if I need to use 2 hooks using refs on the 1 element? Like following:

export const TestComponent = () => {
    const hookRef1 = useHook1();
    const hookRef2 = useHook2();

    return <div ref={el => {
        hookRef1(el) // error
        hookRef2(el) // error
    }}>/*smth else*/</div>

}

How to use the above code correctly?

1

There are 1 best solutions below

0
Владимир Говоров On BEST ANSWER

Following hook returns the RefObject:

const useHook = () => {
    const containerRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        /*some logic*/
    }, []);

    return containerRef; // here it is
}

so we can just pass variable contains useHook() into ref prop like following:

const TestComponent = () => {
    const hookRef = useHook();

    return <div ref={hookRef}>/*smth else*/</div>
}

or we can go this way:

const TestComponent = () => {
    const hookRef = useHook();
    const hookRef2 = useHook2();

    return <div ref={element => { // multiple refs
        hookRef.current = element;
        hookRef2.current = element;
    }}>
        example text
    </div>

}