react-native-web-performance

React Native Web - Performance

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-web-performance" with this command: npx skills add thebushidocollective/han/thebushidocollective-han-react-native-web-performance

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 &#x26;&#x26; (
    &#x3C;Suspense fallback={&#x3C;ActivityIndicator />}>
      &#x3C;Chart />
    &#x3C;/Suspense>
  )}
&#x3C;/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

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

android-jetpack-compose

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi-async-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

storybook-story-writing

No summary provided by upstream source.

Repository SourceNeeds Review