react-native-expert

React Native Expert Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-native-expert" with this command: npx skills add nguyenthienthanh/aura-frog/nguyenthienthanh-aura-frog-react-native-expert

React Native Expert Skill

Expert-level React Native patterns, mobile-specific optimizations, navigation, and platform handling.

Auto-Detection

This skill activates when:

  • Working with React Native projects

  • Detected react-native or expo in package.json

  • Building mobile components

  • Platform-specific code needed

  1. Project Structure

Recommended Structure

src/ ├── components/ # Shared components │ ├── ui/ # Base UI components │ └── common/ # Business components ├── screens/ # Screen components ├── navigation/ # Navigation config ├── hooks/ # Custom hooks ├── services/ # API services ├── stores/ # State management ├── utils/ # Utilities ├── constants/ # App constants ├── types/ # TypeScript types └── assets/ # Images, fonts

  1. Component Patterns

Adaptive Styling Detection

// ✅ GOOD - Detect and use project's styling approach // Check package.json for: nativewind, emotion, styled-components, or use StyleSheet

// NativeWind (Tailwind) import { styled } from 'nativewind'; const StyledView = styled(View); <StyledView className="flex-1 bg-white p-4" />

// StyleSheet (default) const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'white', padding: 16 }, }); <View style={styles.container} />

// Emotion import styled from '@emotion/native'; const Container = styled.Viewflex: 1; background-color: white;;

Performance-Optimized Components

// ✅ GOOD - Memoized list item const ListItem = React.memo(function ListItem({ item, onPress }: Props) { const handlePress = useCallback(() => { onPress(item.id); }, [item.id, onPress]);

return ( <Pressable onPress={handlePress}> <Text>{item.title}</Text> </Pressable> ); });

// ✅ GOOD - Pressable over TouchableOpacity <Pressable onPress={handlePress} style={({ pressed }) => [ styles.button, pressed && styles.buttonPressed ]} android_ripple={{ color: 'rgba(0,0,0,0.1)' }}

<Text>Press Me</Text> </Pressable>

  1. FlatList Optimization

Required Optimizations

// ✅ GOOD - Optimized FlatList <FlatList data={items} renderItem={renderItem} keyExtractor={keyExtractor} // Performance props removeClippedSubviews={true} maxToRenderPerBatch={10} windowSize={5} initialNumToRender={10} getItemLayout={getItemLayout} // If fixed height // Memoized functions ListEmptyComponent={EmptyComponent} ListHeaderComponent={HeaderComponent} ListFooterComponent={FooterComponent} // Prevent re-renders extraData={selectedId} />

// ✅ GOOD - Memoized renderItem const renderItem = useCallback(({ item }: { item: Item }) => ( <ListItem item={item} onPress={handlePress} /> ), [handlePress]);

// ✅ GOOD - Stable keyExtractor const keyExtractor = useCallback((item: Item) => item.id, []);

// ✅ GOOD - getItemLayout for fixed height items const getItemLayout = useCallback(( _data: Item[] | null | undefined, index: number ) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index, }), []);

FlashList Alternative

// ✅ BETTER - Use FlashList for large lists import { FlashList } from '@shopify/flash-list';

<FlashList data={items} renderItem={renderItem} estimatedItemSize={ITEM_HEIGHT} keyExtractor={keyExtractor} />

  1. Navigation (React Navigation)

Type-Safe Navigation

// ✅ GOOD - Define navigation types type RootStackParamList = { Home: undefined; Profile: { userId: string }; Settings: { section?: string }; };

type ProfileScreenProps = NativeStackScreenProps<RootStackParamList, 'Profile'>;

// ✅ GOOD - Type-safe navigation hook import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack';

type NavigationProp = NativeStackNavigationProp<RootStackParamList>;

function MyComponent() { const navigation = useNavigation<NavigationProp>();

const goToProfile = (userId: string) => { navigation.navigate('Profile', { userId }); }; }

Deep Linking

// ✅ GOOD - Configure deep linking const linking = { prefixes: ['myapp://', 'https://myapp.com'], config: { screens: { Home: '', Profile: 'user/:userId', Settings: 'settings', }, }, };

<NavigationContainer linking={linking}> {/* ... */} </NavigationContainer>

  1. Platform-Specific Code

Platform Selection

import { Platform, StyleSheet } from 'react-native';

// ✅ GOOD - Platform.select const styles = StyleSheet.create({ shadow: Platform.select({ ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 3.84, }, android: { elevation: 5, }, default: {}, }), });

// ✅ GOOD - Platform-specific files // Button.ios.tsx // Button.android.tsx // Button.tsx (fallback) import Button from './Button'; // Auto-selects platform

Safe Area Handling

import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';

// ✅ GOOD - SafeAreaView for screens function Screen() { return ( <SafeAreaView style={{ flex: 1 }} edges={['top', 'bottom']}> <Content /> </SafeAreaView> ); }

// ✅ GOOD - useSafeAreaInsets for custom handling function CustomHeader() { const insets = useSafeAreaInsets(); return ( <View style={{ paddingTop: insets.top }}> <HeaderContent /> </View> ); }

  1. Image Handling

Optimized Images

import FastImage from 'react-native-fast-image';

// ✅ GOOD - Use FastImage for network images <FastImage source={{ uri: imageUrl, priority: FastImage.priority.normal, cache: FastImage.cacheControl.immutable, }} style={styles.image} resizeMode={FastImage.resizeMode.cover} />

// ✅ GOOD - Preload images FastImage.preload([ { uri: 'https://example.com/image1.jpg' }, { uri: 'https://example.com/image2.jpg' }, ]);

// ✅ GOOD - Local images with require <Image source={require('./assets/logo.png')} />

  1. Animations

Reanimated Best Practices

import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming, runOnJS, } from 'react-native-reanimated';

// ✅ GOOD - Worklet-based animations function AnimatedCard() { const scale = useSharedValue(1);

const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], }));

const handlePressIn = () => { scale.value = withSpring(0.95); };

const handlePressOut = () => { scale.value = withSpring(1); };

return ( <Pressable onPressIn={handlePressIn} onPressOut={handlePressOut}> <Animated.View style={[styles.card, animatedStyle]}> <Content /> </Animated.View> </Pressable> ); }

Gesture Handler

import { Gesture, GestureDetector } from 'react-native-gesture-handler';

// ✅ GOOD - Gesture-based interactions function SwipeableCard() { const translateX = useSharedValue(0);

const gesture = Gesture.Pan() .onUpdate((e) => { translateX.value = e.translationX; }) .onEnd(() => { translateX.value = withSpring(0); });

const animatedStyle = useAnimatedStyle(() => ({ transform: [{ translateX: translateX.value }], }));

return ( <GestureDetector gesture={gesture}> <Animated.View style={animatedStyle}> <Card /> </Animated.View> </GestureDetector> ); }

  1. Storage & Persistence

import AsyncStorage from '@react-native-async-storage/async-storage'; import * as SecureStore from 'expo-secure-store';

// ✅ GOOD - AsyncStorage for non-sensitive data async function saveSettings(settings: Settings) { await AsyncStorage.setItem('settings', JSON.stringify(settings)); }

// ✅ GOOD - SecureStore for sensitive data async function saveToken(token: string) { await SecureStore.setItemAsync('authToken', token); }

// ✅ GOOD - MMKV for performance-critical storage import { MMKV } from 'react-native-mmkv';

const storage = new MMKV(); storage.set('user.name', 'John'); const name = storage.getString('user.name');

  1. Testing

import { render, fireEvent, waitFor } from '@testing-library/react-native';

// ✅ GOOD - Component testing describe('LoginButton', () => { it('calls onPress when pressed', () => { const onPress = jest.fn(); const { getByText } = render(<LoginButton onPress={onPress} />);

fireEvent.press(getByText('Login'));
expect(onPress).toHaveBeenCalled();

}); });

// ✅ GOOD - Async testing it('shows loading then content', async () => { const { getByTestId, queryByTestId } = render(<DataScreen />);

expect(getByTestId('loading')).toBeTruthy();

await waitFor(() => { expect(queryByTestId('loading')).toBeNull(); expect(getByTestId('content')).toBeTruthy(); }); });

Quick Reference

checklist[12]{area,best_practice}: Lists,Use FlashList or optimized FlatList Images,Use FastImage for network images Navigation,Type-safe with RootStackParamList Styling,Detect project approach (NativeWind/StyleSheet) Platform,Use Platform.select for differences Safe area,Use SafeAreaView or useSafeAreaInsets Animations,Use Reanimated for 60fps Gestures,Use Gesture Handler Storage,SecureStore for tokens AsyncStorage for prefs Performance,Memoize components and callbacks Testing,React Native Testing Library Pressable,Use over TouchableOpacity

Version: 1.3.0

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

stitch-design

No summary provided by upstream source.

Repository SourceNeeds Review
General

angular-expert

No summary provided by upstream source.

Repository SourceNeeds Review
General

visual-pixel-perfect

No summary provided by upstream source.

Repository SourceNeeds Review