React Native performance optimization techniques. Use when optimizing app performance.
/plugin marketplace add IvanTorresEdge/molcajete.ai/plugin install ivantorresedge-react-native-tech-stacks-js-react-native@IvanTorresEdge/molcajete.aiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill covers performance optimization for React Native apps.
Use this skill when:
MEASURE FIRST - Profile before optimizing. Fix actual bottlenecks, not perceived ones.
// Enable profiling in development
if (__DEV__) {
// React DevTools will show component render times
}
# Install Flipper for advanced debugging
# https://fbflipper.com/
// Show FPS and memory in development
import { LogBox } from 'react-native';
if (__DEV__) {
// Performance overlay available via shake gesture
}
// ❌ Bad: Creates new function every render
<Button onPress={() => handlePress(item.id)} />
// ✅ Good: Stable function reference
const handlePress = useCallback((id: string) => {
console.log(id);
}, []);
<Button onPress={() => handlePress(item.id)} />
// ✅ Better: If possible, pass id differently
const handleItemPress = useCallback(() => {
console.log(item.id);
}, [item.id]);
<Button onPress={handleItemPress} />
import { memo } from 'react';
interface ItemCardProps {
item: Item;
onPress: (id: string) => void;
}
export const ItemCard = memo(function ItemCard({
item,
onPress,
}: ItemCardProps): React.ReactElement {
return (
<TouchableOpacity onPress={() => onPress(item.id)}>
<Text>{item.name}</Text>
</TouchableOpacity>
);
});
import { useMemo } from 'react';
function FilteredList({ items, filter }: Props): React.ReactElement {
// Only recompute when items or filter change
const filteredItems = useMemo(() => {
return items.filter((item) =>
item.name.toLowerCase().includes(filter.toLowerCase())
);
}, [items, filter]);
return <FlashList data={filteredItems} {...rest} />;
}
import { useCallback } from 'react';
function ItemList(): React.ReactElement {
const handlePress = useCallback((id: string) => {
// Handle press
}, []);
const renderItem = useCallback(({ item }: { item: Item }) => (
<ItemCard item={item} onPress={handlePress} />
), [handlePress]);
return (
<FlashList
data={items}
renderItem={renderItem}
estimatedItemSize={80}
/>
);
}
import { FlashList } from '@shopify/flash-list';
// ✅ FlashList is 10x faster than FlatList
<FlashList
data={items}
renderItem={({ item }) => <ItemCard item={item} />}
estimatedItemSize={80} // Required for FlashList
keyExtractor={(item) => item.id}
/>
// ✅ Use getItemType for different item layouts
<FlashList
data={items}
renderItem={({ item }) => {
if (item.type === 'header') return <Header />;
return <Item item={item} />;
}}
getItemType={(item) => item.type}
estimatedItemSize={60}
/>
// ✅ Use overrideItemLayout for variable heights
<FlashList
data={items}
renderItem={renderItem}
estimatedItemSize={60}
overrideItemLayout={(layout, item) => {
layout.size = item.type === 'header' ? 100 : 60;
}}
/>
import { Image } from 'expo-image';
// ✅ expo-image is faster than React Native Image
<Image
source={{ uri: imageUrl }}
style={{ width: 200, height: 200 }}
contentFit="cover"
transition={200}
cachePolicy="memory-disk"
/>
// ✅ Request appropriately sized images
const imageUrl = `${baseUrl}?w=400&h=400`;
// ✅ Use blurhash for placeholders
<Image
source={{ uri: imageUrl }}
placeholder={blurhash}
transition={200}
/>
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
// ✅ Animations run on UI thread
function AnimatedBox(): React.ReactElement {
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
return <Animated.View style={animatedStyle} />;
}
// ❌ Bad: JS thread animations
const [scale, setScale] = useState(1);
Animated.timing(scale, { toValue: 2 }).start();
// ✅ Good: Reanimated (runs on UI thread)
const scale = useSharedValue(1);
scale.value = withSpring(2);
npx react-native-bundle-visualizer
// ❌ Bad: Imports entire library
import { format } from 'date-fns';
// ✅ Good: Import only what you need
import format from 'date-fns/format';
// ❌ Bad: Import all icons
import * as Icons from 'lucide-react-native';
// ✅ Good: Import specific icons
import { Home, Search } from 'lucide-react-native';
// Replace moment.js (300KB) with:
// - date-fns (tree-shakeable)
// - dayjs (2KB)
// Replace lodash with:
// - Individual lodash functions
// - Native JavaScript methods
useEffect(() => {
const subscription = eventEmitter.subscribe(handler);
// ✅ Always clean up subscriptions
return () => {
subscription.unsubscribe();
};
}, []);
// ✅ Cancel async operations
useEffect(() => {
let isMounted = true;
fetchData().then((data) => {
if (isMounted) {
setData(data);
}
});
return () => {
isMounted = false;
};
}, []);
// ❌ Inline styles (creates new object every render)
<View style={{ padding: 10 }} />
// ❌ Anonymous functions in render
<Button onPress={() => handlePress()} />
// ❌ FlatList for long lists
<FlatList data={longList} />
// ❌ Unoptimized images
<Image source={{ uri: fullSizeImage }} />
// ✅ NativeWind or StyleSheet
<View className="p-4" />
// ✅ useCallback for handlers
const handlePress = useCallback(() => {...}, []);
// ✅ FlashList for long lists
<FlashList data={longList} estimatedItemSize={80} />
// ✅ Optimized images with expo-image
<Image source={{ uri: optimizedImage }} cachePolicy="memory-disk" />
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.