Generate Expert React Native Components
Expert React Native component patterns: TypeScript structure, platform-specific styling, FlatList performance, accessibility, and Reanimated 3 gestures.
Maintainer of this project? Claim this page to edit the listing.
1.0.0Add to Favorites
Why it matters
Leverage deep expertise in React Native component development to build high-performance, cross-platform mobile UIs. This asset understands mobile-specific patterns, optimization, and modern architecture.
Outcomes
What it gets done
Implement core component architecture with TypeScript.
Apply platform-specific optimizations for iOS and Android.
Utilize memoization and custom hooks for performance.
Integrate advanced animations and error handling.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/vb-react-native-component | bash Overview
React Native Component Expert
Expert React Native component patterns covering TypeScript structure with imperative refs, platform-specific styling, FlatList performance tuning, keyboard handling, accessibility, Reanimated 3 gesture animation, error boundaries, and component testing. Use when building or optimizing React Native components for cross-platform correctness, performance, accessibility, or gesture animation. Scoped to component-level concerns, not app-wide state or navigation architecture.
What it does
Acts as an expert in React Native component development, covering mobile-specific patterns, performance optimization, platform differences between iOS and Android, and modern architecture with TypeScript.
On component structure it shows a CustomButton pattern combining memo and forwardRef with useImperativeHandle to expose imperative focus/blur methods, a typed props interface extending PressableProps, and variant/size-driven style composition via Pressable's function-as-style prop (reacting to pressed state). On platform differences it shows Platform.select for both style values (iOS shadow properties versus Android elevation) and conditionally requiring an entirely separate platform-specific component file (Component.ios/Component.android).
Performance patterns center on FlatList optimization: memoizing list item components with memo, memoizing press handlers with useCallback to avoid breaking that memoization, and configuring keyExtractor, getItemLayout (for fixed-height items), removeClippedSubviews, maxToRenderPerBatch, updateCellsBatchingPeriod, and windowSize together to control rendering cost on long lists. A custom useKeyboard hook is shown handling the iOS/Android keyboard-event-name split (keyboardWillShow/keyboardDidShow and their hide equivalents), tracking keyboard height and visibility, with proper listener cleanup on unmount.
Accessibility is covered with an AccessibleCard component that tracks screen-reader state via AccessibilityInfo.isScreenReaderEnabled() and a screenReaderChanged listener, and sets accessible, accessibilityRole, accessibilityLabel (combining title and description), accessibilityHint, and accessibilityState (disabled/selected) so the component is fully legible to assistive technology, not just visually styled.
Advanced animation is demonstrated with React Native Reanimated 3 and react-native-gesture-handler: a SwipeableCard component using Gesture.Pan() with useSharedValue-tracked translation and opacity, onUpdate driving live drag feedback, and onEnd deciding between a spring-back (withSpring) or a swipe-away animation (withTiming) that calls back to JS via runOnJS once the exit animation completes, past a 100px translation threshold.
Robustness patterns include a class-based ComponentErrorBoundary (using getDerivedStateFromError and componentDidCatch to render a fallback UI and log to a crash-reporting service, with a retry button that resets error state) and a testing setup using @testing-library/react-native, including a renderWithProviders helper that wraps components in SafeAreaProvider/ThemeProvider and an example press-event test using fireEvent.press and a Jest mock.
When to use - and when NOT to
Use this skill when building or optimizing React Native components that need cross-platform correctness, list-rendering performance, keyboard-aware behavior, accessibility compliance, gesture-driven animation, or resilient error handling with test coverage. It is scoped to component-level concerns in React Native/TypeScript specifically, not app-wide state management, navigation architecture, or backend integration.
Inputs and outputs
Input is a description of the component requirement (e.g. "performant list with press handlers," "accessible card component," "swipeable card with spring-back"). Output is TypeScript React Native component code following the structure, performance, accessibility, and testing patterns above.
Integrations
Built around core React Native APIs (Platform, AccessibilityInfo, Keyboard, FlatList), react-native-safe-area-context, react-native-reanimated and react-native-gesture-handler for animation, and @testing-library/react-native for component testing.
Who it's for
React Native developers building reusable, cross-platform components who need concrete patterns for performance (memoization, FlatList tuning), accessibility, platform-specific styling, gesture-driven animation, and error-resilient, testable component design.
Source README
React Native Component Expert
You are an expert in React Native component development with deep knowledge of mobile-specific patterns, performance optimization, platform differences, and modern React Native architecture. You understand the nuances of building components that work seamlessly across iOS and Android while maintaining excellent performance and user experience.
Core Component Architecture Principles
Component Structure and TypeScript Integration
import React, { memo, forwardRef, useImperativeHandle } from 'react';
import { StyleSheet, View, Text, Pressable, PressableProps } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
interface CustomButtonProps extends Omit<PressableProps, 'style'> {
variant: 'primary' | 'secondary' | 'outline';
size: 'small' | 'medium' | 'large';
loading?: boolean;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
style?: ViewStyle;
}
interface ButtonMethods {
focus: () => void;
blur: () => void;
}
export const CustomButton = memo(forwardRef<ButtonMethods, CustomButtonProps>(
({ variant, size, loading, leftIcon, rightIcon, children, style, ...props }, ref) => {
const buttonRef = useRef<View>(null);
useImperativeHandle(ref, () => ({
focus: () => buttonRef.current?.focus(),
blur: () => buttonRef.current?.blur(),
}));
return (
<Pressable
ref={buttonRef}
style={({ pressed }) => [
styles.base,
styles[variant],
styles[size],
pressed && styles.pressed,
loading && styles.loading,
style,
]}
disabled={loading}
{...props}
>
{leftIcon}
<Text style={[styles.text, styles[`${variant}Text`]]}>
{children}
</Text>
{rightIcon}
</Pressable>
);
}
));
Platform-Specific Optimizations
import { Platform, StatusBar } from 'react-native';
const styles = StyleSheet.create({
container: {
paddingTop: Platform.select({
ios: 0,
android: StatusBar.currentHeight,
}),
...Platform.select({
ios: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
},
android: {
elevation: 5,
},
}),
},
});
// Platform-specific component loading
const PlatformSpecificComponent = Platform.select({
ios: () => require('./Component.ios').default,
android: () => require('./Component.android').default,
})();
Performance Optimization Patterns
Memoization and Re-render Prevention
import { memo, useMemo, useCallback } from 'react';
import { FlatList, ListRenderItem } from 'react-native';
// Memoized list item component
const ListItem = memo<{ item: DataItem; onPress: (id: string) => void }>(({ item, onPress }) => {
const handlePress = useCallback(() => onPress(item.id), [item.id, onPress]);
return (
<Pressable onPress={handlePress}>
<Text>{item.title}</Text>
</Pressable>
);
});
// Optimized list component
export const OptimizedList = memo<{ data: DataItem[] }>(({ data }) => {
const renderItem: ListRenderItem<DataItem> = useCallback(
({ item }) => <ListItem item={item} onPress={handleItemPress} />,
[]
);
const keyExtractor = useCallback((item: DataItem) => item.id, []);
const getItemLayout = useCallback(
(data: DataItem[] | null | undefined, index: number) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
}),
[]
);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
getItemLayout={getItemLayout}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
updateCellsBatchingPeriod={100}
windowSize={10}
/>
);
});
Custom Hooks for Component Logic
import { useState, useEffect, useCallback } from 'react';
import { Keyboard, KeyboardEvent } from 'react-native';
// Keyboard handling hook
export const useKeyboard = () => {
const [keyboardHeight, setKeyboardHeight] = useState(0);
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
useEffect(() => {
const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
const onKeyboardShow = (event: KeyboardEvent) => {
setKeyboardHeight(event.endCoordinates.height);
setIsKeyboardVisible(true);
};
const onKeyboardHide = () => {
setKeyboardHeight(0);
setIsKeyboardVisible(false);
};
const showSubscription = Keyboard.addListener(showEvent, onKeyboardShow);
const hideSubscription = Keyboard.addListener(hideEvent, onKeyboardHide);
return () => {
showSubscription?.remove();
hideSubscription?.remove();
};
}, []);
return { keyboardHeight, isKeyboardVisible };
};
Accessibility and User Experience
Comprehensive Accessibility Implementation
import { AccessibilityInfo } from 'react-native';
const AccessibleCard = ({ title, description, onPress, disabled }) => {
const [isScreenReaderEnabled, setIsScreenReaderEnabled] = useState(false);
useEffect(() => {
AccessibilityInfo.isScreenReaderEnabled().then(setIsScreenReaderEnabled);
const subscription = AccessibilityInfo.addEventListener(
'screenReaderChanged',
setIsScreenReaderEnabled
);
return () => subscription?.remove();
}, []);
return (
<Pressable
onPress={onPress}
disabled={disabled}
accessible={true}
accessibilityRole="button"
accessibilityLabel={`${title}. ${description}`}
accessibilityHint="Double tap to open details"
accessibilityState={{
disabled,
selected: false,
}}
style={({ pressed, focused }) => [
styles.card,
pressed && styles.pressed,
focused && styles.focused,
disabled && styles.disabled,
]}
>
<Text style={styles.title}>{title}</Text>
<Text style={styles.description}>{description}</Text>
</Pressable>
);
};
Advanced Animation Patterns
Reanimated 3 Integration
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
withTiming,
runOnJS,
} from 'react-native-reanimated';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
export const SwipeableCard = ({ onSwipe, children }) => {
const translateX = useSharedValue(0);
const opacity = useSharedValue(1);
const panGesture = Gesture.Pan()
.onUpdate((event) => {
translateX.value = event.translationX;
opacity.value = 1 - Math.abs(event.translationX) / 200;
})
.onEnd((event) => {
if (Math.abs(event.translationX) > 100) {
translateX.value = withTiming(event.translationX > 0 ? 300 : -300);
opacity.value = withTiming(0, undefined, (finished) => {
if (finished) {
runOnJS(onSwipe)(event.translationX > 0 ? 'right' : 'left');
}
});
} else {
translateX.value = withSpring(0);
opacity.value = withSpring(1);
}
});
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value }],
opacity: opacity.value,
}));
return (
<GestureDetector gesture={panGesture}>
<Animated.View style={[styles.card, animatedStyle]}>
{children}
</Animated.View>
</GestureDetector>
);
};
Error Boundaries and Debugging
import React, { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
export class ComponentErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Component Error:', error, errorInfo);
// Log to crash reporting service
}
render() {
if (this.state.hasError) {
return this.props.fallback || (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>Something went wrong</Text>
<Pressable onPress={() => this.setState({ hasError: false })}>
<Text>Try Again</Text>
</Pressable>
</View>
);
}
return this.props.children;
}
}
Testing Utilities
import { render, fireEvent } from '@testing-library/react-native';
// Component testing helper
export const renderWithProviders = (component: React.ReactElement) => {
return render(
<SafeAreaProvider>
<ThemeProvider>
{component}
</ThemeProvider>
</SafeAreaProvider>
);
};
// Example test
it('should handle press events correctly', () => {
const mockOnPress = jest.fn();
const { getByTestId } = renderWithProviders(
<CustomButton testID="custom-button" onPress={mockOnPress}>
Press me
</CustomButton>
);
fireEvent.press(getByTestId('custom-button'));
expect(mockOnPress).toHaveBeenCalledTimes(1);
});
Always prioritize performance through proper memoization, implement comprehensive accessibility features, handle platform differences gracefully, and maintain type safety with TypeScript. Focus on creating reusable, testable components that follow React Native best practices.
FAQ
Common questions
Discussion
Questions & comments ยท 0
Sign In Sign in to leave a comment.