Сделаем первое приложение на React Native: список задач. В нём будут TextInput, кнопка добавления, FlatList, отметка выполненных задач и удаление. Такой пример сразу показывает основные элементы мобильного UI.
Создать проект
npx create-expo-app@latest todo-native
cd todo-native
npx expo start
Главный компонент
import { useState } from 'react';
import {
View,
Text,
TextInput,
Pressable,
FlatList,
StyleSheet,
} from 'react-native';
export default function App() {
const [text, setText] = useState('');
const [todos, setTodos] = useState([]);
function addTodo() {
const trimmed = text.trim();
if (!trimmed) return;
setTodos(prev => [
{ id: Date.now().toString(), text: trimmed, done: false },
...prev,
]);
setText('');
}
function toggleTodo(id) {
setTodos(prev =>
prev.map(todo =>
todo.id === id ? { ...todo, done: !todo.done } : todo
)
);
}
function deleteTodo(id) {
setTodos(prev => prev.filter(todo => todo.id !== id));
}
return (
<View style={styles.screen}>
<Text style={styles.title}>Мои задачи</Text>
<View style={styles.form}>
<TextInput
value={text}
onChangeText={setText}
placeholder="Новая задача"
style={styles.input}
onSubmitEditing={addTodo}
/>
<Pressable style={styles.addButton} onPress={addTodo}>
<Text style={styles.addText}>+</Text>
</Pressable>
</View>
<FlatList
data={todos}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<View style={styles.todo}>
<Pressable style={styles.todoText} onPress={() => toggleTodo(item.id)}>
<Text style={[styles.text, item.done && styles.done]}>
{item.text}
</Text>
</Pressable>
<Pressable onPress={() => deleteTodo(item.id)}>
<Text style={styles.delete}>Удалить</Text>
</Pressable>
</View>
)}
/>
</View>
);
}
Стили
const styles = StyleSheet.create({
screen: {
flex: 1,
padding: 20,
paddingTop: 64,
backgroundColor: '#f8fafc',
},
title: {
fontSize: 28,
fontWeight: '800',
marginBottom: 20,
},
form: {
flexDirection: 'row',
gap: 8,
marginBottom: 16,
},
input: {
flex: 1,
backgroundColor: 'white',
borderWidth: 1,
borderColor: '#cbd5e1',
borderRadius: 8,
padding: 12,
},
addButton: {
width: 48,
borderRadius: 8,
backgroundColor: '#2563eb',
alignItems: 'center',
justifyContent: 'center',
},
addText: { color: 'white', fontSize: 24 },
todo: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'white',
borderRadius: 8,
padding: 12,
marginBottom: 8,
},
todoText: { flex: 1 },
text: { fontSize: 16 },
done: { textDecorationLine: 'line-through', color: '#64748b' },
delete: { color: '#dc2626' },
});
Что здесь важно
- View заменяет div.
- Text обязателен для текста.
- TextInput использует onChangeText вместо event.target.value.
- FlatList подходит для списков лучше, чем обычный map.
- Стили пишутся объектами, а не CSS-строками.
Как улучшить приложение
- Добавить счётчик выполненных задач.
- Сохранять задачи в AsyncStorage.
- Добавить фильтры: все, активные, выполненные.
- Разделить App на компоненты TodoItem и TodoForm.
- Добавить пустое состояние, когда задач нет.
Компонент TodoItem
function TodoItem({ item, onToggle, onDelete }) {
return (
<View style={styles.todo}>
<Pressable style={styles.todoText} onPress={() => onToggle(item.id)}>
<Text style={[styles.text, item.done && styles.done]}>{item.text}</Text>
</Pressable>
<Pressable onPress={() => onDelete(item.id)}>
<Text style={styles.delete}>Удалить</Text>
</Pressable>
</View>
);
}
Вынос TodoItem делает главный App короче. Это тот же принцип компонентов, что и в обычном React: отдельный смысловой блок лучше вынести в отдельную функцию.
Как довести первое приложение до нормального вида
Todo-приложение полезно не самим списком задач, а тем, что на нём удобно тренировать мобильные привычки: крупные области нажатия, клавиатуру, пустые состояния, сохранение данных и разбиение на компоненты.
После того как todo-экран заработал, качество растёт не от новых библиотек, а от мелких мобильных деталей. Проверьте касания, клавиатуру, пустое состояние, длинные задачи и поведение на маленьком экране.
Проверка на телефоне
- кнопки достаточно крупные для пальца;
- поле ввода не закрывается клавиатурой;
- список нормально прокручивается;
- текст читается на маленьком экране;
- после ошибки приложение не падает без объяснения.
Что добавить следующим шагом
- пустое состояние: «Пока нет задач»;
- счётчик выполненных задач;
- фильтры: все, активные, выполненные;
- сохранение задач в AsyncStorage;
- разделение на TodoForm и TodoItem.
Проверка на реальном устройстве
Откройте приложение на реальном устройстве и попробуйте пользоваться им одной рукой. Если кнопка удаления слишком маленькая, поле ввода закрывается клавиатурой или текст плохо читается, это видно только на телефоне.
Главный вывод
React Native похож на React по мышлению, но не по деталям интерфейса. Здесь важны размеры касаний, поведение клавиатуры, скорость списков и отличия Android от iOS.



