¡Veamos cómo usar ref como una prop normal!
Con la llegada de React 19, finalmente podemos despedirnos del molesto forwardRef en muchos casos sencillos. Uno de los cambios más sutiles —pero poderosos— fue la mejora en el comportamiento del ref, que ahora puede pasarse como una prop común a componentes funcionales.
Este cambio ayuda a que nuestro código sea más limpio e intuitivo, especialmente en librerías como React Native, donde usamos ref con frecuencia para acceder a elementos como TextInput, ScrollView, FlatList, etc.
🧠 Antes: forwardRef obligatorio
Hasta React 18, si queríamos que un componente personalizado aceptara un ref, estábamos obligados a envolver el componente con `forwardRef`. Mira:
// MiInput.tsx (antes)
import React, { forwardRef } from 'react'
import { TextInput, TextInputProps } from 'react-native'
export const MiInput = forwardRef<TextInput, TextInputProps>((props, ref) => {
return <TextInput ref={ref} {...props} />
})
En el componente padre, usábamos el ref normalmente:
// Padre.tsx
import React, { useRef } from 'react'
import { View, Button, TextInput } from 'react-native'
import { MiInput } from './MiInput'
export const Padre = () => {
const inputRef = useRef<TextInput>(null)
return (
<View>
<MiInput ref={inputRef} />
<Button title="Enfocar" onPress={() => inputRef.current?.focus()} />
</View>
)
}
📌 Problema: estabas obligado a usar `forwardRef en MiInput`, aunque fuera un componente simple.
✅ Ahora: ref como una prop común
Con React 19, si tu componente pasa el ref directamente a un elemento compatible, ya no necesitas usar `forwardRef`.
Mira cómo queda el mismo ejemplo con React 19:
// MiInput.tsx (React 19)
import React from 'react'
import { TextInput, TextInputProps } from 'react-native'
export const MiInput = (props: TextInputProps & { ref?: React.Ref<TextInput> }) => {
return <TextInput {...props} />
}
Y en el componente padre, ningún cambio:
// Padre.tsx
import React, { useRef } from 'react'
import { View, Button, TextInput } from 'react-native'
import { MiInput } from './MiInput'
export const Padre = () => {
const inputRef = useRef<TextInput>(null)
return (
<View>
<MiInput ref={inputRef} />
<Button title="Enfocar" onPress={() => inputRef.current?.focus()} />
</View>
)
}
✅ ¡Sin forwardRef! React ahora entiende que si pasas un ref como prop y este se encamina directamente a un elemento interno (TextInput en este caso), todo funciona automáticamente.
🔥 Y más: ref con cleanup (React 19)
Otra mejora sutil: los callbacks de ref ahora pueden devolver una función de cleanup (limpieza), al igual que los efectos (useEffect):
<TextInput
ref={(node) => {
console.log('Montado', node)
return () => {
console.log('Desmontado', node)
}
}}
/>
⚠️ Limitaciones
No todo es color de rosa. Esta simplificación solo funciona si:
- El
refse pasa directamente a un elemento nativo o del DOM. - Tu componente no intercepta ni modifica el `ref` internamente.
Si quieres aplicar lógica extra al ref o combinarlo con otro, seguirá siendo necesario usar forwardRef.
📦 Conclusión
React 19 trae pequeños cambios que, en conjunto, hacen que el desarrollo sea más fluido y elegante. Con esta mejora en el uso de ref, logramos:
- Eliminar
forwardRefde muchos componentes. - Reducir el boilerplate.
- Tener un código más simple y directo.
🧩 Cuándo sigue siendo necesario usar forwardRef
Incluso con las mejoras de React 19, el forwardRef sigue siendo necesario en algunos escenarios más avanzados. Mira un ejemplo real:
❌ Ejemplo que no funciona sin forwardRef
import React from 'react'
import { View, Text, ViewProps } from 'react-native'
export const MiCaja = (props: ViewProps & { ref?: React.Ref<View> }) => {
const { style, children, ...rest } = props
return (
<View ref={props.ref} style={[{ padding: 12 }, style]} {...rest}>
<Text>{children}</Text>
</View>
)
}
En este caso, React no garantiza que el ref se pase correctamente, ya que el componente no es "transparente".
✅ Correcto: usando forwardRef
import React, { forwardRef } from 'react'
import { View, Text, ViewProps } from 'react-native'
export const MiCaja = forwardRef<View, ViewProps>(({ style, children, ...rest }, ref) => {
return (
<View ref={ref} style={[{ padding: 12 }, style]} {...rest}>
<Text>{children}</Text>
</View>
)
})
⚠️ Otros casos que aún requieren forwardRef
| Situación | ¿forwardRef necesario? |
|---|---|
| El Ref se aplica directamente a un elemento DOM/Nativo | ❌ No |
| El Ref es interceptado o modificado internamente | ✅ Sí |
El Ref necesita ser almacenado o combinado con otro (mergeRefs) |
✅ Sí |
| El componente necesita exponer imperativamente una API vía `ref` | ✅ Sí |
A pesar de las mejoras, forwardRef sigue siendo una herramienta esencial en componentes más complejos. Usa el nuevo comportamiento siempre que sea posible, pero identifica cuándo sigue siendo necesario el patrón tradicional.
Top comments (0)