I was trying to call the child component method from parent component and I was trying to use useRef. In the future, the SayHi method will be update hook state in the child component. Unfortunately, I have bugs with I can't deal with.
Line: ref.current.SayHi();
Property 'SayHi' does not exist on type 'ForwardRefExoticComponent<{ name: string; } & RefAttributes<{ SayHi: () => void; }>>'.
Line: < Child name="Adam" ref={ref}/>
Type 'RefObject void; }>>>' is not assignable to type '((instance: { SayHi: () => void; } | null) => void) | RefObject<{ SayHi: () => void; }> | null | undefined'. Type 'RefObject void; }>>>' is not assignable to type 'RefObject<{ SayHi: () => void; }>'. Property 'SayHi' is missing in type 'ForwardRefExoticComponent<{ name: string; } & RefAttributes<{ SayHi: () => void; }>>' but required in type '{ SayHi: () => void; }'.
Full test.tsx file:
import React, { useRef, forwardRef, useImperativeHandle, Ref } from 'react'
const Parent = () => {
const ref = useRef<typeof Child>(null);
const onButtonClick = () => {
if (ref.current) {
ref.current.SayHi();
}
};
return (
<div>
<Child name="Adam" ref={ref}/>
<button onClick={onButtonClick}>Log console</button>
</div>
);
}
const Child = forwardRef((props: {name: string}, ref: Ref<{SayHi: () => void}>)=> {
const {name} = props;
useImperativeHandle(ref, () => ({ SayHi }));
function SayHi() { console.log("Hello " + name); }
return <div>{name}</div>;
});
I deeply ask for help on this topic.
You require to extract the ref type elsewhere:
interface RefObject {
SayHi: () => void
}
then just refer to it in both places
const Child = forwardRef((props: {name: string}, ref: Ref<RefObject>)=> {
const {name} = props;
useImperativeHandle(ref, () => ({ SayHi }));
function SayHi() { console.log("Hello " + name); }
return <div>{name}</div>;
});
const Parent = () => {
const ref = useRef<RefObject>(null);
const onButtonClick = () => {
if (ref.current) {
ref.current.SayHi();
}
};
return (
<div>
<Child name="Adam" ref={ref}/>
<button onClick={onButtonClick}>Log console</button>
</div>
);
}