
React Native Web Performance
- 46 installs
- 186 repo stars
- Updated July 19, 2026
- thebushidocollective/han
Helps with frontend development tasks during AI-assisted development.
About
react-native-web-performance is a Claude Code skill for frontend development. It helps solo builders move faster with AI-assisted coding.
- react-native-web-performance
- Frontend Development
- AI-coding skill
React Native Web Performance by the numbers
- 46 all-time installs (skills.sh)
- Ranked #1,329 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/thebushidocollective/han --skill react-native-web-performanceAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 46 |
|---|---|
| repo stars | ★ 186 |
| Last updated | July 19, 2026 |
| Repository | thebushidocollective/han ↗ |
What it does
Helps with frontend development tasks during AI-assisted development.
Files
React Native Web - Performance
Performance optimization patterns for React Native Web, focusing on bundle size, rendering performance, and web-specific optimizations.
Key Concepts
Code Splitting
Use dynamic imports for lazy loading:
import React, { lazy, Suspense } from 'react';
import { View, ActivityIndicator } from 'react-native';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<ActivityIndicator />}>
<HeavyComponent />
</Suspense>
);
}Memoization
Prevent unnecessary re-renders with React.memo and hooks:
import React, { memo, useMemo, useCallback } from 'react';
interface Props {
items: Item[];
onItemPress: (id: string) => void;
}
export const ItemList = memo(function ItemList({ items, onItemPress }: Props) {
const sortedItems = useMemo(
() => items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
const handlePress = useCallback(
(id: string) => {
onItemPress(id);
},
[onItemPress]
);
return (
<View>
{sortedItems.map(item => (
<Item key={item.id} item={item} onPress={handlePress} />
))}
</View>
);
});FlatList for Large Lists
Use FlatList for efficient rendering of long lists:
import { FlatList, View, Text } from 'react-native';
interface Item {
id: string;
title: string;
}
function ItemsList({ items }: { items: Item[] }) {
return (
<FlatList
data={items}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<View>
<Text>{item.title}</Text>
</View>
)}
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
removeClippedSubviews
/>
);
}Best Practices
Optimize Images
✅ Use optimized image formats and lazy loading:
import { Image } from 'react-native';
function OptimizedImage({ uri }: { uri: string }) {
return (
<Image
source={{ uri }}
style={{ width: 200, height: 200 }}
resizeMode="cover"
// Web-specific: lazy loading
{...(Platform.OS === 'web' && {
loading: 'lazy',
})}
/>
);
}Avoid Inline Functions
✅ Use useCallback for event handlers:
import { useCallback } from 'react';
function Component({ onSave }: { onSave: (data: Data) => void }) {
const [data, setData] = useState<Data>();
const handleSave = useCallback(() => {
if (data) {
onSave(data);
}
}, [data, onSave]);
return <Button onPress={handleSave} title="Save" />;
}Optimize StyleSheet
✅ Create StyleSheet outside component:
import { StyleSheet } from 'react-native';
// Good - created once
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
});
function Component() {
return <View style={styles.container} />;
}
// Bad - recreated on every render
function BadComponent() {
const styles = StyleSheet.create({
container: { flex: 1 },
});
return <View style={styles.container} />;
}Examples
Virtualized List with Optimization
import React, { useCallback, memo } from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
interface Item {
id: string;
title: string;
description: string;
}
interface ItemCardProps {
item: Item;
onPress: (id: string) => void;
}
const ItemCard = memo(function ItemCard({ item, onPress }: ItemCardProps) {
const handlePress = useCallback(() => {
onPress(item.id);
}, [item.id, onPress]);
return (
<Pressable onPress={handlePress}>
<View style={styles.card}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.description}>{item.description}</Text>
</View>
</Pressable>
);
});
export function OptimizedList({ items, onItemPress }: {
items: Item[];
onItemPress: (id: string) => void;
}) {
const renderItem = useCallback(
({ item }: { item: Item }) => (
<ItemCard item={item} onPress={onItemPress} />
),
[onItemPress]
);
const keyExtractor = useCallback((item: Item) => item.id, []);
return (
<FlatList
data={items}
renderItem={renderItem}
keyExtractor={keyExtractor}
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
removeClippedSubviews
getItemLayout={(data, index) => ({
length: 80,
offset: 80 * index,
index,
})}
/>
);
}
const styles = StyleSheet.create({
card: {
padding: 16,
backgroundColor: '#fff',
marginBottom: 8,
borderRadius: 8,
},
title: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 4,
},
description: {
fontSize: 14,
color: '#666',
},
});Dynamic Imports
import React, { lazy, Suspense, useState } from 'react';
import { View, Button, ActivityIndicator } from 'react-native';
// Lazy load heavy components
const Chart = lazy(() => import('./Chart'));
const DataTable = lazy(() => import('./DataTable'));
export function Dashboard() {
const [showChart, setShowChart] = useState(false);
return (
<View>
<Button
title="Show Chart"
onPress={() => setShowChart(true)}
/>
{showChart && (
<Suspense fallback={<ActivityIndicator />}>
<Chart />
</Suspense>
)}
</View>
);
}Optimized Context
import React, { createContext, useContext, useMemo, ReactNode } from 'react';
interface User {
id: string;
name: string;
}
interface UserContextValue {
user: User | null;
isLoading: boolean;
}
const UserContext = createContext<UserContextValue | undefined>(undefined);
export function UserProvider({
user,
isLoading,
children,
}: {
user: User | null;
isLoading: boolean;
children: ReactNode;
}) {
// Memoize context value to prevent unnecessary re-renders
const value = useMemo(
() => ({ user, isLoading }),
[user, isLoading]
);
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
}
export function useUser() {
const context = useContext(UserContext);
if (context === undefined) {
throw new Error('useUser must be used within UserProvider');
}
return context;
}Common Patterns
Debounced Input
import { useState, useEffect } from 'react';
import { TextInput } from 'react-native';
function SearchInput({ onSearch }: { onSearch: (query: string) => void }) {
const [query, setQuery] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
onSearch(query);
}, 300);
return () => clearTimeout(timer);
}, [query, onSearch]);
return (
<TextInput
value={query}
onChangeText={setQuery}
placeholder="Search..."
/>
);
}Intersection Observer (Web)
import { useEffect, useRef, useState } from 'react';
import { View, Platform } from 'react-native';
function LazyLoadComponent({ children }: { children: React.ReactNode }) {
const [isVisible, setIsVisible] = useState(false);
const ref = useRef<View>(null);
useEffect(() => {
if (Platform.OS !== 'web') {
setIsVisible(true);
return;
}
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.disconnect();
}
},
{ threshold: 0.1 }
);
const element = ref.current as any;
if (element) {
observer.observe(element);
}
return () => observer.disconnect();
}, []);
return (
<View ref={ref}>
{isVisible ? children : <View style={{ height: 200 }} />}
</View>
);
}Bundle Size Optimization
// webpack.config.js or metro.config.js
module.exports = {
resolve: {
alias: {
// Use lightweight alternatives
'react-native$': 'react-native-web',
'lodash': 'lodash-es',
},
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
},
},
},
},
};Anti-Patterns
❌ Don't create StyleSheet inside render:
// Bad
function Component() {
const styles = StyleSheet.create({ container: { flex: 1 } });
return <View style={styles.container} />;
}
// Good
const styles = StyleSheet.create({ container: { flex: 1 } });
function Component() {
return <View style={styles.container} />;
}❌ Don't use inline functions in FlatList:
// Bad
<FlatList
data={items}
renderItem={({ item }) => <Item item={item} onPress={() => handlePress(item.id)} />}
/>
// Good
const renderItem = useCallback(({ item }) => (
<Item item={item} onPress={handlePress} />
), [handlePress]);
<FlatList data={items} renderItem={renderItem} />❌ Don't import entire libraries:
// Bad
import _ from 'lodash';
// Good
import debounce from 'lodash/debounce';❌ Don't render all items in long lists:
// Bad
{items.map(item => <Item key={item.id} item={item} />)}
// Good
<FlatList
data={items}
renderItem={({ item }) => <Item item={item} />}
/>Related Skills
- react-native-web-core: Core React Native Web concepts
- react-native-web-styling: Optimized styling patterns
- react-native-web-testing: Performance testing strategies