@@ -1599,22 +1599,62 @@ When you don't know what to choose, prefer runtime checking and throwing over ty
15991599
16001600#### forwardRef/createRef
16011601
1602- Check the [ Hooks section] ( https://github.com/typescript-cheatsheets/react/blob/main/README.md# hooks) for ` useRef ` .
1602+ For ` useRef ` , check the [ Hooks section] ( /docs/basic/getting-started/ hooks#useref ) .
16031603
1604- ` createRef ` :
1604+ #### Ref as a Prop (Recommended for React 19+)
1605+
1606+ In React 19+, you can access ` ref ` directly as a prop in function components - no ` forwardRef ` wrapper needed.
1607+
1608+ ##### Option 1: Inherit all props from a native element
1609+
1610+ Use ` ComponentPropsWithRef ` to inherit all props from a native element.
16051611
16061612``` tsx
1607- import { createRef , PureComponent } from " react" ;
1613+ import { ComponentPropsWithRef , useRef } from " react" ;
16081614
1609- class CssThemeProvider extends PureComponent <Props > {
1610- private rootRef = createRef <HTMLDivElement >(); // like this
1611- render() {
1612- return <div ref = { this .rootRef } >{ this .props .children } </div >;
1613- }
1615+ function MyInput(props : ComponentPropsWithRef <" input" >) {
1616+ return <input { ... props } />;
1617+ }
1618+
1619+ // Usage in parent component
1620+ function Parent() {
1621+ const inputRef = useRef <HTMLInputElement >(null );
1622+
1623+ return <MyInput ref = { inputRef } placeholder = " Type here..." />;
16141624}
16151625```
16161626
1617- ` forwardRef ` :
1627+ ##### Option 2: Explicit typing
1628+
1629+ If you have custom props and want fine-grained control, you can explicitly type the ref:
1630+
1631+ ``` tsx
1632+ import { Ref , useRef } from " react" ;
1633+
1634+ interface MyInputProps {
1635+ placeholder: string ;
1636+ ref: Ref <HTMLInputElement >;
1637+ }
1638+
1639+ function MyInput(props : MyInputProps ) {
1640+ return <input { ... props } />;
1641+ }
1642+
1643+ // Usage in parent component
1644+ function Parent() {
1645+ const inputRef = useRef <HTMLInputElement >(null );
1646+
1647+ return <MyInput ref = { inputRef } placeholder = " Type here..." />;
1648+ }
1649+ ```
1650+
1651+ ** Read more** : [ Wrapping/Mirroring a HTML Element] ( /docs/advanced/patterns_by_usecase#wrappingmirroring-a-html-element )
1652+
1653+ #### Legacy Approaches (Pre-React 19)
1654+
1655+ ##### forwardRef
1656+
1657+ For React 18 and earlier, use ` forwardRef ` :
16181658
16191659``` tsx
16201660import { forwardRef , ReactNode } from " react" ;
@@ -1648,7 +1688,7 @@ interface Props {
16481688export const FancyButton = forwardRef (
16491689 (
16501690 props : Props ,
1651- ref : Ref < HTMLButtonElement > // <-- here!
1691+ ref : Ref < HTMLButtonElement > // <-- explicit immutable ref type
16521692 ) => (
16531693 <button ref = { ref } className = " MyClassName" type = { props .type } >
16541694 { props .children }
@@ -1659,42 +1699,47 @@ export const FancyButton = forwardRef(
16591699
16601700</details >
16611701
1662- If you are grabbing the props of a component that forwards refs, use [ ` ComponentPropsWithRef ` ] ( https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a05cc538a42243c632f054e42eab483ebf1560ab/types/react/index.d.ts#L770 ) .
1702+ If you need to grab props from a component that forwards refs, use [ ` ComponentPropsWithRef ` ] ( https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a05cc538a42243c632f054e42eab483ebf1560ab/types/react/index.d.ts#L770 ) .
16631703
1664- ` ref ` as a prop:
1704+ ##### createRef
16651705
1666- React 19, you can access ref as prop for function components .
1706+ ` createRef ` is mostly used for class components. Function components typically rely on ` useRef ` instead .
16671707
16681708``` tsx
1669- function MyInput({ placeholder , ref }) {
1670- return <input placeholder = { placeholder } ref = { ref } />;
1671- }
1709+ import { createRef , PureComponent } from " react" ;
16721710
1673- // In parent
1674- <MyInput ref = { ref } />;
1711+ class CssThemeProvider extends PureComponent <Props > {
1712+ private rootRef = createRef <HTMLDivElement >();
1713+
1714+ render() {
1715+ return <div ref = { this .rootRef } >{ this .props .children } </div >;
1716+ }
1717+ }
16751718```
16761719
1677- Read more [ ` ref ` as a prop ] ( https://react.dev/blog/2024/12/05/react-19#ref-as-a-prop ) .
1720+ #### Generic Components with Refs
16781721
1679- #### Generic forwardRefs
1722+ Generic components typically require manual ref handling since their generic nature prevents automatic type inference. Here are the main approaches:
16801723
1681- Read more context in https://fettblog.eu/typescript-react-generic-forward-refs/ :
1724+ Read more context in [ this article ] ( https://fettblog.eu/typescript-react-generic-forward-refs/ ) .
16821725
1683- ##### Option 1 - Wrapper component
1726+ ##### Option 1: Wrapper Component
16841727
1685- ``` ts
1686- type ClickableListProps <T > = {
1728+ The most straightforward approach is to manually handle refs through props:
1729+
1730+ ``` tsx
1731+ interface ClickableListProps <T > {
16871732 items: T [];
16881733 onSelect: (item : T ) => void ;
16891734 mRef? : React .Ref <HTMLUListElement > | null ;
1690- };
1735+ }
16911736
16921737export function ClickableList<T >(props : ClickableListProps <T >) {
16931738 return (
16941739 <ul ref = { props .mRef } >
16951740 { props .items .map ((item , i ) => (
16961741 <li key = { i } >
1697- < button onClick = {(el ) => props.onSelect(item)}> Select < / button >
1742+ <button onClick = { () => props .onSelect (item )} >Select</button >
16981743 { item }
16991744 </li >
17001745 ))}
@@ -1703,17 +1748,19 @@ export function ClickableList<T>(props: ClickableListProps<T>) {
17031748}
17041749```
17051750
1706- ##### Option 2 - Redeclare forwardRef
1751+ ##### Option 2: Redeclare forwardRef
17071752
1708- ``` ts
1709- // Redeclare forwardRef
1753+ For true ` forwardRef ` behavior with generics, extend the module declaration:
1754+
1755+ ``` tsx
1756+ // Redeclare forwardRef to support generics
17101757declare module " react" {
17111758 function forwardRef<T , P = {}>(
17121759 render : (props : P , ref : React .Ref <T >) => React .ReactElement | null
17131760 ): (props : P & React .RefAttributes <T >) => React .ReactElement | null ;
17141761}
17151762
1716- // Just write your components like you're used to!
1763+ // Now you can use forwardRef with generics normally
17171764import { forwardRef , ForwardedRef } from " react" ;
17181765
17191766interface ClickableListProps <T > {
@@ -1729,7 +1776,7 @@ function ClickableListInner<T>(
17291776 <ul ref = { ref } >
17301777 { props .items .map ((item , i ) => (
17311778 <li key = { i } >
1732- < button onClick = {(el ) => props.onSelect(item)}> Select < / button >
1779+ <button onClick = { () => props .onSelect (item )} >Select</button >
17331780 { item }
17341781 </li >
17351782 ))}
@@ -1740,10 +1787,12 @@ function ClickableListInner<T>(
17401787export const ClickableList = forwardRef (ClickableListInner );
17411788```
17421789
1743- ##### Option 3 - Call signature
1790+ ##### Option 3: Call Signature
17441791
1745- ``` ts
1746- // Add to `index.d.ts`
1792+ If you need both generic support and proper forwardRef behavior with full type inference, you can use the call signature:
1793+
1794+ ``` tsx
1795+ // Add to your type definitions (e.g. in `index.d.ts` file)
17471796interface ForwardRefWithGenerics extends React .FC <WithForwardRefProps <Option >> {
17481797 <T extends Option >(props : WithForwardRefProps <T >): ReturnType <
17491798 React .FC <WithForwardRefProps <T >>
@@ -1754,15 +1803,20 @@ export const ClickableListWithForwardRef: ForwardRefWithGenerics =
17541803 forwardRef (ClickableList );
17551804```
17561805
1757- Credits: https://stackoverflow.com/a/73795494
1806+ Credits: [ https://stackoverflow.com/a/73795494 ] ( https://stackoverflow.com/a/73795494 )
17581807
1759- #### More Info
1808+ ::: note
1809+ Option 1 is usually sufficient and clearer. Use Option 2 when you specifically need ` forwardRef ` behavior. Use Option 3 for advanced library scenarios requiring both generics and full forwardRef type inference.
1810+ :::
17601811
1761- - https://medium.com/@martin_hotell/react-refs-with-typescript-a32d56c4d315
1812+ #### Additional Resources
17621813
1763- You may also wish to do [ Conditional Rendering with ` forwardRef ` ] ( https://github.com/typescript-cheatsheets/react/issues/167 ) .
1814+ - [ React refs with TypeScript] ( https://medium.com/@martin_hotell/react-refs-with-typescript-a32d56c4d315 )
1815+ - [ Conditional rendering with forwardRef] ( https://github.com/typescript-cheatsheets/react/issues/167 )
17641816
1765- [ Something to add? File an issue] ( https://github.com/typescript-cheatsheets/react/issues/new ) .
1817+ ---
1818+
1819+ [ Something to add? File an issue] ( https://github.com/typescript-cheatsheets/react/issues/new )
17661820
17671821<!-- END-SECTION:forward-create-ref-->
17681822
0 commit comments