From 454407734bf3dfb32a688902d0c044f5eec46c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateo=20Guzm=C3=A1n?= Date: Sun, 4 Sep 2022 02:02:11 +0200 Subject: [PATCH 1/4] docs(hooks): improving useImperativeHandle example --- docs/basic/getting-started/hooks.md | 47 ++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/docs/basic/getting-started/hooks.md b/docs/basic/getting-started/hooks.md index 7fafad2f..e8455de0 100644 --- a/docs/basic/getting-started/hooks.md +++ b/docs/basic/getting-started/hooks.md @@ -210,21 +210,52 @@ 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 inferrence here as well + countdownEl.current.start(); + } + }, []); + + return ; } ``` + +### See also: + +- [Using ForwardRefRenderFunction](https://stackoverflow.com/a/62258685/5415299) ## Custom Hooks From 0e29f354e556a4eb73e16ea79ab22f196353bff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateo=20Guzm=C3=A1n?= Date: Sun, 4 Sep 2022 02:15:50 +0200 Subject: [PATCH 2/4] Update hooks.md --- docs/basic/getting-started/hooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/basic/getting-started/hooks.md b/docs/basic/getting-started/hooks.md index e8455de0..91bf42f2 100644 --- a/docs/basic/getting-started/hooks.md +++ b/docs/basic/getting-started/hooks.md @@ -244,7 +244,7 @@ function App() { useEffect(() => { if (countdownEl.current) { - // start() has type inferrence here as well + // start() has type inference here as well countdownEl.current.start(); } }, []); From 67079af8807fd1d45f80f4e128886b299946388a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateo=20Guzm=C3=A1n?= Date: Sun, 4 Sep 2022 10:15:06 +0200 Subject: [PATCH 3/4] chore(readme): running codegen --- README.md | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) 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): From 666aab1c551278679380e75851b80a3f6e386968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateo=20Guzm=C3=A1n?= Date: Sun, 4 Sep 2022 10:56:42 +0200 Subject: [PATCH 4/4] chore: formatting files --- docs/basic/getting-started/hooks.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/basic/getting-started/hooks.md b/docs/basic/getting-started/hooks.md index 91bf42f2..883815c1 100644 --- a/docs/basic/getting-started/hooks.md +++ b/docs/basic/getting-started/hooks.md @@ -226,15 +226,15 @@ const Countdown = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ // start() has type inference here start() { - alert('Start'); + alert("Start"); }, })); return
Countdown
; }); ``` - -```tsx + +```tsx // The component uses the Countdown component import Countdown, { CountdownHandle } from "./Countdown.tsx"; @@ -252,9 +252,9 @@ function App() { return ; } ``` - + ### See also: - + - [Using ForwardRefRenderFunction](https://stackoverflow.com/a/62258685/5415299) ## Custom Hooks