Context
I had a component that I wanted to pass the ref prop into. To do that with React, you have to use React.forwardRef function and pass the second argument to the appropriate child component.
It would look like this:
export const YourComponent = React.forwardRef<HTMLDivElement, YourComponentProps>( function ComponentNameForDebugging( { className, children }, ref ) { return ( <Wrapper className={className} ref={ref} > {children} </Wrapper> ); } )
And now, what if I wanted to access that ref inside the YourComponent. Normally I would try to access it through ref.current, but here it's different.
The ref variable (forwardRef's second parameter) doesn't have .current property since it is a function. A function that takes HTMLDivElement as an argument.
Solution
In such a case, what I need to do is:
- create a new ref inside 
YourComponent, let's call ittestRef, - in 
Wrappercomponent, add lambda function as a value ofrefprop. With HTMLDivElement as a parameter, - assign the value of a lambda's parameter to 
testRef.current - call the 
ref(el: HTMLDivElement | null)and pass the lambda's parameter as an argument. 
This would look like this:
export const YourComponent = React.forwardRef<HTMLDivElement, YourComponentProps>( function ComponentNameForDebugging({ className, children }, ref) { const testRef = useRef<HTMLDivElement | null>(null); return ( <Wrapper className={className} ref={(el) => { testRef.current = el; if (typeof ref === 'function') { ref(el); } }} > {children} </Wrapper> ); } );
but it doesn't look the best! We could create a simple utility class for that or.... steal it from StackOverflow from the author you don't remember and can't find at the time of writing a blog post!
import { MutableRefObject, Ref } from 'react'; export const assignRefs = <T extends unknown>(...refs: Ref<T | null>[]) => { return (node: T | null) => { refs.forEach((r) => { if (typeof r === 'function') { r(node); } else if (r) { (r as MutableRefObject<T | null>).current = node; } }); }; };
and the final YourComponent's form is...
export const YourComponent = React.forwardRef<HTMLDivElement, YourComponentProps>( function ComponentNameForDebugging({ className, children }, ref) { const testRef = useRef<HTMLDivElement | null>(null); return ( <Wrapper className={className} ref={assignRefs(testRef, ref)}> {children} </Wrapper> ); } );
    
Top comments (0)