Pressable и кнопки
В React Native нет <button>. Вместо него — Pressable, TouchableOpacity, TouchableHighlight.
Pressable
Современный способ. Даёт полный контроль над состоянием нажатия.
import { Pressable, Text, StyleSheet } from 'react-native';
export default function Button() {
return (
<Pressable
onPress={() => console.log('нажато')}
onLongPress={() => console.log('долгое нажатие')}
style={({ pressed }) => [
styles.button,
pressed && styles.pressed,
]}
>
<Text style={styles.label}>Нажми</Text>
</Pressable>
);
}
style может быть функцией, получающей { pressed }.
Состояния
<Pressable
style={({ pressed, hovered, focused }) => [
styles.base,
pressed && styles.pressed,
hovered && styles.hovered,
focused && styles.focused,
]}
>
{({ pressed }) => (
<Text>{pressed ? 'Нажато' : 'Нажми'}</Text>
)}
</Pressable>
Или children — функция с состоянием.
TouchableOpacity
Классический вариант с эффектом прозрачности:
import { TouchableOpacity, Text } from 'react-native';
<TouchableOpacity
onPress={handlePress}
activeOpacity={0.7}
disabled={isDisabled}
>
<Text>Нажми</Text>
</TouchableOpacity>
При нажатии opacity меняется. Просто, но меньше контроля.
TouchableHighlight
Подсветка фона при нажатии:
<TouchableHighlight
onPress={handlePress}
underlayColor="#ddd"
>
<Text>Нажми</Text>
</TouchableHighlight>
Компонент кнопки
import { Pressable, Text, StyleSheet, ActivityIndicator } from 'react-native';
type ButtonProps = {
label: string;
onPress: () => void;
variant?: 'primary' | 'secondary';
disabled?: boolean;
loading?: boolean;
};
export function Button({
label,
onPress,
variant = 'primary',
disabled = false,
loading = false,
}: ButtonProps) {
const isDisabled = disabled || loading;
return (
<Pressable
onPress={onPress}
disabled={isDisabled}
style={({ pressed }) => [
styles.base,
styles[variant],
pressed && styles.pressed,
isDisabled && styles.disabled,
]}
>
{loading ? (
<ActivityIndicator color="#fff" />
) : (
<Text style={styles.label}>{label}</Text>
)}
</Pressable>
);
}
const styles = StyleSheet.create({
base: {
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 8,
alignItems: 'center',
justifyContent: 'center',
minHeight: 48,
},
primary: { backgroundColor: '#c1442e' },
secondary: { backgroundColor: '#fff', borderWidth: 1, borderColor: '#c1442e' },
pressed: { opacity: 0.7 },
disabled: { opacity: 0.5 },
label: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
});
Если ты уже знаешь React
В вебе — <button onClick={...}>. В React Native — <Pressable onPress={...}>. Название события другое: onPress вместо onClick.
Другие события
onPress— кликonLongPress— долгое нажатиеonPressIn— начало нажатияonPressOut— конец нажатияonHoverIn/onHoverOut— только с мышью (web, iPad)
Доступность
<Pressable
onPress={onPress}
accessibilityRole="button"
accessibilityLabel="Отправить форму"
accessibilityHint="Отправляет данные на сервер"
accessibilityState={{ disabled: isDisabled }}
>
Итоги
- Нет
<button>— используйPressable onPressвместоonClickstyleможет быть функциейTouchableOpacity— простой вариантActivityIndicatorдля загрузки