diff --git a/README.md b/README.md index 5e4f96d9..012edb53 100644 --- a/README.md +++ b/README.md @@ -559,22 +559,53 @@ function Foo() { #### useImperativeHandle -_We don't have much here, but this is from [a discussion in our issues](https://github.com/typescript-cheatsheets/react/issues/106). Please contribute if you have anything to add!_ +Based on this [Stackoverflow answer](https://stackoverflow.com/a/69292925/5415299): ```tsx -type ListProps = { - items: ItemType[]; - innerRef?: React.Ref<{ scrollToItem(item: ItemType): void }>; +// Countdown.tsx + +// Define the handle types which will be passed to the forwardRef +export type CountdownHandle = { + start: () => void; }; -function List(props: ListProps) { - useImperativeHandle(props.innerRef, () => ({ - scrollToItem() {}, +type CountdownProps = {}; + +const Countdown = forwardRef((props, ref) => { + useImperativeHandle(ref, () => ({ + // start() has type inference here + start() { + alert("Start"); + }, })); - return null; + + return
Countdown
; +}); +``` + +```tsx +// The component uses the Countdown component + +import Countdown, { CountdownHandle } from "./Countdown.tsx"; + +function App() { + const countdownEl = useRef(null); + + useEffect(() => { + if (countdownEl.current) { + // start() has type inference here as well + countdownEl.current.start(); + } + }, []); + + return ; } ``` +##### See also: + +- [Using ForwardRefRenderFunction](https://stackoverflow.com/a/62258685/5415299) + #### Custom Hooks If you are returning an array in your Custom Hook, you will want to avoid type inference as TypeScript will infer a union type (when you actually want different types in each position of the array). Instead, use [TS 3.4 const assertions](https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/#const-assertions): diff --git a/docs/basic/getting-started/hooks.md b/docs/basic/getting-started/hooks.md index 7fafad2f..883815c1 100644 --- a/docs/basic/getting-started/hooks.md +++ b/docs/basic/getting-started/hooks.md @@ -210,22 +210,53 @@ function Foo() { ## useImperativeHandle -_We don't have much here, but this is from [a discussion in our issues](https://github.com/typescript-cheatsheets/react/issues/106). Please contribute if you have anything to add!_ +Based on this [Stackoverflow answer](https://stackoverflow.com/a/69292925/5415299): ```tsx -type ListProps = { - items: ItemType[]; - innerRef?: React.Ref<{ scrollToItem(item: ItemType): void }>; +// Countdown.tsx + +// Define the handle types which will be passed to the forwardRef +export type CountdownHandle = { + start: () => void; }; -function List(props: ListProps) { - useImperativeHandle(props.innerRef, () => ({ - scrollToItem() {}, +type CountdownProps = {}; + +const Countdown = forwardRef((props, ref) => { + useImperativeHandle(ref, () => ({ + // start() has type inference here + start() { + alert("Start"); + }, })); - return null; + + return
Countdown
; +}); +``` + +```tsx +// The component uses the Countdown component + +import Countdown, { CountdownHandle } from "./Countdown.tsx"; + +function App() { + const countdownEl = useRef(null); + + useEffect(() => { + if (countdownEl.current) { + // start() has type inference here as well + countdownEl.current.start(); + } + }, []); + + return ; } ``` +### See also: + +- [Using ForwardRefRenderFunction](https://stackoverflow.com/a/62258685/5415299) + ## Custom Hooks If you are returning an array in your Custom Hook, you will want to avoid type inference as TypeScript will infer a union type (when you actually want different types in each position of the array). Instead, use [TS 3.4 const assertions](https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/#const-assertions):