Pressable es un componente moderno de React Native para manejar toques, que reemplaza los obsoletos TouchableHighlight, TouchableOpacity y TouchableWithoutFeedback. Pressable proporciona una API unificada con detección de los estados pressed, hovered y focused. El componente se introdujo en React Native 0.63 y Meta lo recomienda para todos los proyectos nuevos. Más información en la documentación de Meta.
Puntos clave
Pressable es un componente de React Native que proporciona una interfaz unificada para manejar todo tipo de toques. A diferencia de tres componentes Touchable diferentes (TouchableHighlight, TouchableOpacity, TouchableWithoutFeedback), Pressable los reemplaza a todos con un sistema flexible de estados y estilos.
El componente se introdujo en React Native 0.63 (septiembre de 2020). Según Meta (2026), el 70% de los nuevos proyectos en React Native usan Pressable en lugar de los componentes Touchable. Pressable resuelve el problema clave de Touchable: una API fragmentada y la necesidad de cambiar entre componentes para diferentes efectos.
A diferencia de TouchableOpacity, donde el efecto de presión está fijo (cambio de opacidad), Pressable proporciona una función que recibe el estado actual. El desarrollador decide cómo responder visualmente a una pulsación: cambiar color, escala, sombra o una combinación de efectos. Esto da control total sobre la UX.
Pressable define tres estados de interacción: pressed (dedo en pantalla), hovered (cursor sobre el elemento en Web/TV), focused (elemento con foco de teclado). Cada estado activa el callback correspondiente y se pasa a la función de estilo y a la función render hija.
| Estado | Condición | Reacción típica |
|---|---|---|
| pressed | Dedo en pantalla o clic mantenido | Cambio de opacidad, escala o color de fondo |
| hovered | Cursor sobre el elemento (Web, TV) | Resaltado, sombra, subrayado |
| focused | Elemento con foco de teclado | Contorno, borde, cambio de color |
Importante: hovered y focused solo funcionan en plataformas con soporte de puntero (Web, Android TV, Apple TV). En dispositivos móviles solo está disponible pressed. Para aplicaciones multiplataforma, diseña las reacciones visuales teniendo en cuenta esta limitación.
<Pressable
style={({ pressed }) => [
styles.button,
pressed && styles.buttonPressed,
]}
onPress={handlePress}>
{({ pressed }) => (
<Text style={pressed ? styles.textPressed : styles.text}>
{pressed ? 'Release' : 'Press'}
</Text>
)}
</Pressable>La API de Pressable incluye cuatro callbacks principales: onPress (pulsación completa con liberación), onLongPress (pulsación larga), onPressIn (inicio del toque) y onPressOut (fin del toque). La combinación de onPressIn y onPressOut permite crear animaciones personalizadas.
Props adicionales: delayLongPress (retardo de pulsación larga, por defecto 500 ms), pressRetentionOffset (área fuera de la cual se cancela la pulsación), android_ripple (efecto ripple en Android). Nota: Ripple solo funciona en Android 5+.
<Pressable
onPress={() => console.log('Presionado')}
onLongPress={() => console.log('Presión larga')}
onPressIn={() => console.log('Dedo abajo')}
onPressOut={() => console.log('Dedo arriba')}
delayLongPress={300}
android_ripple={{ color: 'rgba(0,0,0,0.1)', borderless: false }}
style={styles.button}>
<Text>Press me</Text>
</Pressable>onPress solo se llama si el dedo se levanta dentro del área del componente (considerando pressRetentionOffset). Si el usuario mueve el dedo fuera de los límites, onPress no se activa, evitando pulsaciones falsas. onPressOut se llama en cualquier caso al liberar.
hitSlop es una prop de Pressable que extiende el área táctil más allá de los límites visibles del componente. Es crítico para elementos pequeños: iconos, casillas de verificación, botones de opción. Apple HIG recomienda un tamaño mínimo de objetivo táctil de 44×44 puntos. hitSlop permite cumplir este requisito sin cambiar el tamaño visual.
hitSlop acepta un objeto { top, bottom, left, right } o un solo número para todos los lados. Los valores se especifican en píxeles lógicos (dp/pt). Para iconos de 24×24, se recomienda un hitSlop de al menos 10–12 en cada lado para alcanzar el objetivo táctil de 44×44.
<Pressable
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
onPress={handleIconPress}
style={styles.iconButton}>
<Icon name="star" size={24} />
</Pressable>pressRetentionOffset — el inverso de hitSlop: define el área en la que el usuario puede salir de los límites del componente sin cancelar la pulsación. Por defecto es igual a hitSlop. Si necesitas que la pulsación se mantenga al salir de los límites, aumenta pressRetentionOffset.
Pressable vs Touchable — una pregunta clave al elegir un componente para manejar toques. TouchableOpacity, TouchableHighlight y TouchableWithoutFeedback son componentes obsoletos que no se eliminarán pero no recibirán nuevas funcionalidades. Meta recomienda Pressable para proyectos nuevos.
Ventajas clave de Pressable: una API unificada para todos los tipos de efectos, acceso al estado pressed para estilos personalizados, soporte de estados hovered/focused, hitSlop y pressRetentionOffset, callback onLongPress sin configuración adicional. TouchableOpacity solo es adecuado para cambios simples de opacidad.
| Escenario | Touchable | Pressable |
|---|---|---|
| Pulsación simple | TouchableOpacity | Pressable + opacity en style |
| Resaltado de fondo | TouchableHighlight | Pressable + backgroundColor |
| Sin efecto visual | TouchableWithoutFeedback | Pressable con style vacío |
| Pulsación larga | onLongPress en cualquier Touchable | onLongPress en Pressable |
| Animación personalizada | Animated + onPressIn/Out | Pressable + useAnimatedStyle |
| Ripple en Android | TouchableNativeFeedback | Pressable + android_ripple |
Pressable permite crear elementos interactivos complejos con mínimo código. A continuación, un ejemplo de un botón animado con cambio de escala al pulsar y efecto ripple en Android. Este botón reemplaza la combinación TouchableOpacity + Animated.
const AnimatedButton = ({ title, onPress }) => {
const scale = React.useRef(new Animated.Value(1)).current;
const handlePressIn = () => {
Animated.spring(scale, {
toValue: 0.96,
useNativeDriver: true,
}).start();
};
const handlePressOut = () => {
Animated.spring(scale, {
toValue: 1,
friction: 3,
useNativeDriver: true,
}).start();
};
return (
<Pressable
onPress={onPress}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
android_ripple={{ color: 'rgba(255,255,255,0.3)' }}
style={styles.button}>
<AnimatedView style={[styles.inner, { transform: [{ scale }] }]}>
<Text style={styles.text}>{title}</Text>
</AnimatedView>
</Pressable>
);
};Importante: usa useNativeDriver: true para animaciones en Pressable. Esto traslada la animación al hilo nativo, evitando caídas de fotogramas durante pulsaciones rápidas. El controlador nativo es compatible con transform y opacity en todas las plataformas.
Preguntas frecuentes
No, Pressable tiene una API diferente. TouchableOpacity aplica opacidad automáticamente al pulsar. Pressable requiere especificar el estilo explícitamente mediante una función de estado. El reemplazo es trivial: pasa style={({ pressed }) => [{ opacity: pressed ? 0.5 : 1 }]}.
Usa la prop android_ripple con un objeto { color, borderless }. El color del ripple se especifica en formato rgba. Para botones redondos, usa borderless: true. Ripple solo funciona en Android 5+. En iOS, usa animación personalizada.
Pressable tiene protección incorporada contra pulsaciones accidentales durante el desplazamiento. Si el usuario hace scroll en una lista, onPress no se llama. Este comportamiento se puede configurar mediante pressRetentionOffset y delayPressIn.
Usa la prop onLongPress — soporte incorporado para pulsación larga. El retardo se configura mediante delayLongPress (por defecto 500 ms). Para menús contextuales y arrastrar y soltar, combina onLongPress con onPressIn.
Sí, Pressable soporta el estado focused para navegación por teclado en Android TV, Apple TV y Web. Usa estilo mediante { focused } para mostrar el foco. En dispositivos móviles, el estado focused no es aplicable.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también