I'm trying to forward an object of ref in typescript, but I'm facing an issue to correctly type them.
This are my refs and how I pass them inside my component.
const storyRef = useRef<HTMLElement>(null);
const parcoursRef = useRef<HTMLElement>(null);
const projectRef = useRef<HTMLElement>(null);
const refs = useRef({ storyRef, parcoursRef, projectRef });
...
...
<Navbar ref={refs} setShowModal={setShowModal} />
Inside my component I type them this way:
const Navbar = React.forwardRef<
React.MutableRefObject<{
storyRef: React.RefObject<HTMLElement>;
parcoursRef: React.RefObject<HTMLElement>;
projectRef: React.RefObject<HTMLElement>;
}>,
ModalProps
>(({ setShowModal }, ref) => {
This is the error I have:
Type 'MutableRefObject<{ storyRef: RefObject; parcoursRef: RefObject; projectRef: RefObject; }>' is not assignable to type 'Ref<MutableRefObject<{ storyRef: RefObject; parcoursRef: RefObject; projectRef: RefObject; }>> | undefined'. Type 'MutableRefObject<{ storyRef: RefObject; parcoursRef: RefObject; projectRef: RefObject; }>' is not assignable to type 'RefObject<MutableRefObject<{ storyRef: RefObject; parcoursRef: RefObject; projectRef: RefObject; }>>'.
React does not directly support Forwarding multiple ref in typescript. However fear not, there is a real solution called the useImperativeHandle hook. You can also create unlimited refs
to child elements and even functions.
My example has a child component which shows you can easily forward refs to:
All with typescript goodness.
//Child Component
//Create your ref types here
export type RefHandler = {
pressAlert: () => void;
inputRef: RefObject<HTMLInputElement>;
};
const Child = forwardRef<RefHandler, Props>((props, ref) => {
const submitRef = useRef<HTMLButtonElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
//Initialise your refs here
useImperativeHandle(ref, () => ({
inputRef: inputRef,
pressAlert: () => submitRef?.current?.click()
}));
return (
<div>
<p>Child Component</p>
<input type="text" value="lorem ipsum" ref={inputRef} />
<br />
<button onClick={() => alert("Alert pressed")} ref={submitRef}>
Alert
</button>
</div>
);
});
//Parent
export default function Parent() {
const childRef = useRef<RefHandler>(null);
return (
<>
<p>Parent</p>
<button
onClick={() => {
alert(childRef?.current?.inputRef?.current?.value);
}}
>
Read child input
</button>
<button onClick={() => childRef?.current?.pressAlert()}>
Press child button
</button>
<hr />
<Child ref={childRef} />
</>
);
}
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