I have a function component that forwards the incoming ref from the parent to a div
that it is rendering. I also want to create a ref inside the component and assign it to the same div
. But I can't since an element takes only one ref. Am I doing something wrong or is there a workaround for an issue like this?
The ref
coming from the parent is a React.Ref
, but I need a React.RefObject
to pass it to 3rd party hooks like react-use's clickAway
: https://github.com/streamich/react-use/blob/master/docs/useClickAway.md
Here is the example component:
import React, { useRef } from 'react';
type Props = React.PropsWithoutRef<JSX.IntrinsicElements['div']>;
function Component({ ...props }: Props, ref: React.Ref<HTMLDivElement>) {
const wrapper = useRef<HTMLDivElement>(null);
return (
<div
{...props}
ref={ref}
// ref={wrapper}
/>
);
}
export default React.forwardRef(Component);
const mergeRefs = (...refs) => {
return node => {
for (const ref of refs) {
ref.current = node
}
}
}
import React from "react"
export default () => {
const ref1 = React.useRef(null)
const ref2 = React.useRef(null)
return (
<div
ref={node => {
ref1.current = node
ref2.current = node
}}
>
Hello
</div>
)
}
Credit for the examples goes to this article.
interface RefObject<T> {
readonly current: T | null;
}
type RefCallback<T> = { bivarianceHack(instance: T | null): void }["bivarianceHack"];
type Ref<T> = RefCallback<T> | RefObject<T> | null;
function useSyncRefs<TType>(
...refs: (
| React.MutableRefObject<TType | null>
| ((instance: TType) => void)
| null
)[]
) {
let cache = React.useRef(refs);
React.useEffect(() => {
cache.current = refs;
}, [refs]);
return React.useCallback(
(value: TType) => {
for (let ref of cache.current) {
if (ref == null) {
console.log('ref is null');
continue;
}
if (typeof ref === 'function') {
console.log('ref is a function. Returning called function');
ref(value)
} else {
console.log('returning the value: ', value);
ref.current = value
};
}
},
[cache]
);
};
You can see it in action in this Expo Snack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With