10 промтов для React Native: компоненты, навигация, API
Каждый день я как разработчик React Native пишу однотипные запросы в AI, чтобы ускорить работу. Chat‑GPT, Claude или Copilot — неважно, главное — правильно сформулировать промт. В этой подборке — 10 проверенных формулировок, которые я сам использую для UI‑компонентов, навигации, работы с API и оптимизации. Никакой воды — только конкретика с кодом и результатами.
1. Создание кастомного компонента с динамическими пропсами
Проблема: Нужно быстро набросать переиспользуемый компонент UserCard с поддержкой разных состояний (загрузка, ошибка, данные). Писать с нуля вручную — терять время.
Промт:
Напиши React Native компонент
UserCard, который принимает пропсыname,avatarUrl,loadingиerror. В состоянии загрузки покажиActivityIndicator, при ошибке — текст ошибки, иначе — аватар, имя и email. ИспользуйStyleSheet. Верни готовый код.
Результат:
import React from 'react';
import { View, Text, Image, ActivityIndicator, StyleSheet } from 'react-native';
interface UserCardProps {
name?: string;
email?: string;
avatarUrl?: string;
loading: boolean;
error?: string | null;
}
const UserCard: React.FC<UserCardProps> = ({ name, email, avatarUrl, loading, error }) => {
if (loading) return <ActivityIndicator size="large" color="#0000ff" />;
if (error) return <Text style={styles.error}>{error}</Text>;
return (
<View style={styles.card}>
<Image source={{ uri: avatarUrl }} style={styles.avatar} />
<Text style={styles.name}>{name}</Text>
<Text style={styles.email}>{email}</Text>
</View>
);
};
export default UserCard;
Вывод: Промт экономит 5–10 минут ручного написания и покрывает типичные кейсы. Адаптируй под свои типы — и в бой.
2. FlatList с бесконечной подгрузкой
Проблема: Реализовать ленту постов с пагинацией и индикатором загрузки в конце списка. Частая задача, но нужно не забыть про onEndReached и useCallback.
Промт:
Напиши компонент
InfiniteListна React Native с FlatList, который принимаетdata,renderItem,loadMore(функция),hasMore(boolean). При достижении конца списка (onEndReached) вызывайloadMore, покажиActivityIndicatorв Footer, еслиhasMoretrue. Используй useCallback для loadMore. Верни полный код компонента.
Результат:
import React, { useCallback } from 'react';
import { FlatList, ActivityIndicator, StyleSheet, View } from 'react-native';
interface InfiniteListProps<T> {
data: T[];
renderItem: ({ item }: { item: T }) => JSX.Element;
loadMore: () => void;
hasMore: boolean;
}
function InfiniteList<T>({ data, renderItem, loadMore, hasMore }: InfiniteListProps<T>) {
const handleLoadMore = useCallback(() => {
if (hasMore) loadMore();
}, [hasMore, loadMore]);
const footer = hasMore ? <ActivityIndicator style={styles.footer} /> : null;
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(_, index) => index.toString()}
onEndReached={handleLoadMore}
onEndReachedThreshold={0.5}
ListFooterComponent={footer}
/>
);
}
export default InfiniteList;
Вывод: Универсальный компонент для любой версии React Native. Меняй keyExtractor под свой тип данных — готово.
3. Навигация с React Navigation (Stack + Tabs)
Проблем: Нужно настроить связку Stack Navigator в модальном режиме и нижние табы. Документация хороша, но промт даёт скелет за секунду.
Промт:
Напиши конфигурацию React Navigation для приложения: Bottom Tab Navigator с тремя вкладками (Home, Search, Profile). Внутри Home используй Stack Navigator с экранами HomeScreen и DetailsScreen. Покажи код с
NavigationContainer,createBottomTabNavigator,createNativeStackNavigator. Используй Typescript.
Результат:
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from '../screens/HomeScreen';
import DetailsScreen from '../screens/DetailsScreen';
import SearchScreen from '../screens/SearchScreen';
import ProfileScreen from '../screens/ProfileScreen';
type HomeStackParamList = {
Home: undefined;
Details: { itemId: number };
};
const Stack = createNativeStackNavigator<HomeStackParamList>();
const Tab = createBottomTabNavigator();
function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
);
}
export default function AppNavigator() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStack} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
Вывод: Подходит для 90% приложений. Добавь иконки через tabBarIcon — и готово.
4. Кастомный хук для запроса данных (fetch / axios)
Проблем: Не хочется дублировать логику загрузки, ошибок и отмены запросов. Нужен хук useFetch.
Промт:
Напиши кастомный хук
useFetch<T>(url: string, options?: RequestInit)на TypeScript для React Native, который возвращает `{ data: T
| null, loading: boolean, error: string | null, refetch: () => void }`. Используй useEffect с очисткой (AbortController). Пример с fetch. Верни код.
Результат:
import { useState, useEffect, useCallback, useRef } from 'react';
interface UseFetchResult<T> {
data: T | null;
loading: boolean;
error: string | null;
refetch: () => void;
}
export function useFetch<T>(url: string, options?: RequestInit): UseFetchResult<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const abortRef = useRef<AbortController | null>(null);
const fetchData = useCallback(async () => {
abortRef.current?.abort();
const controller = new AbortController();
abortRef.current = controller;
setLoading(true);
setError(null);
try {
const response = await fetch(url, { ...options, signal: controller.signal });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const json = await response.json();
setData(json as T);
} catch (err: any) {
if (err.name !== 'AbortError') setError(err.message);
} finally {
setLoading(false);
}
}, [url, options]);
useEffect(() => {
fetchData();
return () => abortRef.current?.abort();
}, [fetchData]);
return { data, loading, error, refetch: fetchData };
}
Вывод: Хук избавляет от бойлерплейта. Замени fetch на axios по аналогии.
5. Анимированный вход/выход компонента (Animated API)
Проблем: Нужно добавить плавное появление модального окна или тултипа. Вручную писать анимации долго.
Промт:
Напиши React Native компонент
FadeInView, который оборачивает дочерние элементы и анимирует появление с прозрачностью от 0 до 1 при монтировании. ИспользуйAnimated.Value,Animated.timing. Длительность 300ms. Используй функциональный компонент с хуками.
Результат:
import React, { useRef, useEffect } from 'react';
import { Animated, ViewStyle } from 'react-native';
interface FadeInViewProps {
style?: ViewStyle;
children: React.ReactNode;
}
const FadeInView: React.FC<FadeInViewProps> = ({ style, children }) => {
const opacity = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(opacity, {
toValue: 1,
duration: 300,
useNativeDriver: true,
}).start();
}, []);
return (
<Animated.View style={[{ opacity }, style]}>
{children}
</Animated.View>
);
};
export default FadeInView;
Вывод: Минимум кода — максимум эффекта. Легко расширить до анимации сдвига или масштаба.
6. Обработка клавиатуры (KeyboardAvoidingView + dismiss)
Проблем: Форма входа уезжает под клавиатуру. Нужно стандартное решение.
Промт:
Напиши компонент
KeyboardSafeView, который оборачивает контент вKeyboardAvoidingView(поведение 'padding' для iOS, 'height' для Android) и добавляетTouchableWithoutFeedbackдля скрытия клавиатуры по тапу вне поля ввода. ИспользуйPlatform.
Результат:
import React from 'react';
import {
KeyboardAvoidingView,
TouchableWithoutFeedback,
Keyboard,
Platform,
StyleSheet,
ViewProps,
} from 'react-native';
const KeyboardSafeView: React.FC<ViewProps> = ({ children, style }) => {
return (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={[styles.container, style]}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
{children}
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: { flex: 1 },
});
export default KeyboardSafeView;
Вывод: Единый компонент для обеих платформ. Экономит часы дебага адаптации.
7. Скелетон загрузки (Skeleton placeholder)
Проблем: Пользователь видит пустой экран во время загрузки данных. Скелетоны улучшают восприятие (perceived performance).
Промт:
Напиши компонент
SkeletonBoxдля React Native, который рисует прямоугольник с анимированной пульсацией (прозрачность меняется от 0.2 до 0.8). Пропсы:width,height,borderRadius. ИспользуйAnimated.loopиAnimated.sequence.
Результат:
import React, { useRef, useEffect } from 'react';
import { Animated, ViewStyle } from 'react-native';
interface SkeletonBoxProps {
width: number | string;
height: number;
borderRadius?: number;
}
const SkeletonBox: React.FC<SkeletonBoxProps> = ({ width, height, borderRadius = 4 }) => {
const pulseAnim = useRef(new Animated.Value(0.2)).current;
useEffect(() => {
const pulse = Animated.sequence([
Animated.timing(pulseAnim, { toValue: 0.8, duration: 800, useNativeDriver: true }),
Animated.timing(pulseAnim, { toValue: 0.2, duration: 800, useNativeDriver: true }),
]);
Animated.loop(pulse).start();
}, []);
const animatedStyle: Animated.WithAnimatedObject<ViewStyle> = {
width: width as any,
height,
borderRadius,
backgroundColor: '#E1E9EE',
opacity: pulseAnim,
};
return <Animated.View style={animatedStyle} />;
};
export default SkeletonBox;
Вывод: Классический скелетон за 30 секунд. Комбинируй несколько блоков для имитации макета.
8. Работа с AsyncStorage (сохранение токена)
Проблем: Нужно сохранять JWT токен локально. Используем @react-native-async-storage/async-storage.
Промт:
Напиши кастомные функции для работы с AsyncStorage:
setItem(key, value),getItem(key),removeItem(key). Значения сериализуй через JSON.stringify/parse. Обработай ошибки. На TypeScript. Покажи пример сохранения и чтения токена.
Результат:
import AsyncStorage from '@react-native-async-storage/async-storage';
const STORAGE_KEYS = {
AUTH_TOKEN: '@auth_token',
} as const;
async function setItem<T>(key: string, value: T): Promise<void> {
try {
await AsyncStorage.setItem(key, JSON.stringify(value));
} catch (e) {
console.error('Storage set error', e);
}
}
async function getItem<T>(key: string): Promise<T | null> {
try {
const raw = await AsyncStorage.getItem(key);
return raw ? (JSON.parse(raw) as T) : null;
} catch (e) {
console.error('Storage get error', e);
return null;
}
}
async function removeItem(key: string): Promise<void> {
try {
await AsyncStorage.removeItem(key);
} catch (e) {
console.error('Storage remove error', e);
}
}
export { STORAGE_KEYS, setItem, getItem, removeItem };
Вывод: Типизированная обёртка — безопасно и удобно. Меньше бойлерплейта в каждом экране.
9. i18n для мультиязычности (i18next + react-i18next)
Проблем: Нужно быстро подключить локализацию с переключением языка. Промт генерирует конфиг за секунду.
Промт:
Настрой i18next для React Native. Покажи код инициализации с ресурсами для 'en' и 'ru' (по 3 строки), компонент с useTranslation и кнопку переключения языка. Используй react-i18next. Не забудь про
languageDetector(можно заглушку).
Результат:
// i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n.use(initReactI18next).init({
resources: {
en: { translation: { welcome: 'Welcome', logout: 'Logout', settings: 'Settings' } },
ru: { translation: { welcome: 'Добро пожаловать', logout: 'Выйти', settings: 'Настройки' } },
},
lng: 'en',
fallbackLng: 'en',
interpolation: { escapeValue: false },
});
export default i18n;
// В компоненте:
import React from 'react';
import { Button, Text, View } from 'react-native';
import { useTranslation } from 'react-i18next';
const SettingsScreen: React.FC = () => {
const { t, i18n } = useTranslation();
const toggleLang = () => i18n.changeLanguage(i18n.language === 'en' ? 'ru' : 'en');
return (
<View>
<Text>{t('settings')}</Text>
<Button title={t('logout')} onPress={() => {}} />
<Button title="Switch language" onPress={toggleLang} />
</View>
);
};
Вывод: Полный рабочий скелет за один промт. Останется добавить реальные переводы.
10. Обработка deep linking через React Navigation
Проблем: Настроить универсальные ссылки (Universal Links / App Links) без чтения всей документации.
Промт:
Настрой конфигурацию deep linking для React Navigation. Приложение имеет Stack с экранами Home и Details (параметр itemId). Пропиши linking config с префиксом 'myapp://' и путь '/details/:itemId'. Покажи код подключения в NavigationContainer. Используй TypeScript.
Результат:
import { LinkingOptions } from '@react-navigation/native';
import { RootStackParamList } from './types';
const linking: LinkingOptions<RootStackParamList> = {
prefixes: ['myapp://', 'https://myapp.com'],
config: {
screens: {
Home: '',
Details: 'details/:itemId',
},
},
};
// В App.tsx:
<NavigationContainer linking={linking}>
{/* ... */}
</NavigationContainer>
Вывод: Минимальная настройка — и приложение реагирует на ссылки. Тестируй через npx uri-scheme open myapp://details/42 --ios.
Заключение
Все 10 промтов я использую в ежедневной работе. Они покрывают 80% типовых задач — от UI до интеграций. Сохрани эту статью в закладки, или, ещё лучше, скопируй промты в свой инструмент AI. А если хочешь больше таких шпаргалок — подпишись на блог Asibiont, чтобы не пропустить продолжение.
Комментарии