Skip to content

Instantly share code, notes, and snippets.

@Venryx
Last active February 9, 2023 22:36
Show Gist options
  • Save Venryx/7cff24b17867da305fff12c6f8ef6f96 to your computer and use it in GitHub Desktop.
Save Venryx/7cff24b17867da305fff12c6f8ef6f96 to your computer and use it in GitHub Desktop.
Using "useImperativeHandle" in a React functional component, with automatic TypeScript typing
import {forwardRef, useImperativeHandle, ForwardRefExoticComponent, RefAttributes, Ref} from "react";
export type Handle<T> = T extends ForwardRefExoticComponent<RefAttributes<infer T2>> ? T2 : never;
export const Parent = (props: {})=> {
let childHandle: Handle<typeof Child>;
return (
<div onClick={()=>childHandle.SayHi()}>
<Child name="Bob" ref={c=>childHandle = c}/>
</div>
);
};
export const Child = forwardRef((props: {name: string}, ref: Ref<{SayHi}>)=> {
const {name} = props;
// expose internal functions; what we return in the callback below is what gets sent to the "ref" callback in Parent
useImperativeHandle(ref, () => ({ SayHi }));
function SayHi() { console.log("Saying hello from: " + name); }
return <div>{name}</div>;
});
@Rendez
Copy link

Rendez commented May 3, 2022

Isn't React.ElementRef<typeof Child> doing the same as type Handle<T> = T extends ForwardRefExoticComponent<RefAttributes<infer T2>> ? T2 : never;?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment