-
-
Save Venryx/7cff24b17867da305fff12c6f8ef6f96 to your computer and use it in GitHub Desktop.
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>; | |
}); |
Great! It works perfect, but It would be great if there are some kinds of explanation of this.
I found that how it works it's simply extract Ref type from forwarding component.
That's right, this is necessary when you already have a ref inside a component but you need to insert another ref in a parent component that uses that component to retrieve some information from it
I got ts errors:
TS2339: Property 'SayHi' does not exist on type 'never'.
TS2322: Type '{ SayHi: any; } | null' is not assignable to type 'never'. Type 'null' is not assignable to type 'never'.
@lilywang711 Are you using the latest versions of TypeScript (I'm at 3.9.6)? And are you using any non-standard TypeScript settings? (perhaps more of the "strict" options?)
For reference, this is (the trimmed version of) my tsconfig.json:
{
"compilerOptions": {
"module": "ES2015", // leave the imports/exports alone (webpack will convert them to "require")
"moduleResolution": "node",
"target": "esnext", // babel targets es2015 (ie. transpiles our code to it), so it's fine for TS to target es-next
"lib": [
"es5",
"es6",
"ESNext",
"dom"
],
"jsx": "react",
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"alwaysStrict": true,
}
}
@Venryx Yes you are right, when I changed 'strict' from true to false, the error disappeared, thanks!
Isn't React.ElementRef<typeof Child>
doing the same as type Handle<T> = T extends ForwardRefExoticComponent<RefAttributes<infer T2>> ? T2 : never;
?
Great! It works perfect, but It would be great if there are some kinds of explanation of this.
I found that how it works it's simply extract Ref type from forwarding component.