React Native vs React Web

Understand the key differences between React for web and React Native for mobile. Learn when to use each platform and how to leverage their unique capabilities.

Advertisement Space - top-comparison

Google AdSense: horizontal

Quick Comparison

FeatureReact WebReact Native
RenderingDOM (Virtual DOM)Native UI Components
StylingCSS, CSS-in-JS, SassStyleSheet API, Limited CSS
NavigationURL-based, Browser HistoryStack-based, Gestures
AnimationsCSS, Web Animations APIAnimated API, Reanimated
PerformanceJIT CompilationNative Bridge, Hermes
Dev ToolsChrome DevToolsReact Native Debugger, Flipper
Package Managernpm, yarn, pnpmnpm + CocoaPods/Gradle
Hot ReloadFast RefreshFast Refresh
TestingJest, RTL, CypressJest, RTL, Detox
DistributionWeb hosting, CDNApp Store, Google Play

Architecture & Platform Differences

Understand the fundamental differences between React Web and React Native

While React Web and React Native share the same core principles and syntax, they target different platforms with unique architectures, rendering engines, and capabilities.

React Web

1// React Web - DOM-based rendering
2import React, { useState } from 'react';
3import './styles.css';
4
5// Web Component using HTML elements and CSS
6const WebComponent = () => {
7 const [isHovered, setIsHovered] = useState(false);
8 const [clickCount, setClickCount] = useState(0);
9
10 return (
11 <div className="container">
12 <h1 className="title">React Web Application</h1>
13
14 {/* HTML Elements */}
15 <div
16 className="card"
17 onMouseEnter={() => setIsHovered(true)}
18 onMouseLeave={() => setIsHovered(false)}
19 style={{
20 transform: isHovered ? 'scale(1.05)' : 'scale(1)',
21 transition: 'transform 0.3s ease'
22 }}
23 >
24 <img
25 src="/image.jpg"
26 alt="Web image"
27 className="card-image"
28 />
29 <p className="card-text">
30 This runs in a web browser using the DOM
31 </p>
32 </div>
33
34 {/* Web-specific APIs */}
35 <button
36 onClick={() => {
37 setClickCount(prev => prev + 1);
38 // Web APIs
39 window.localStorage.setItem('clicks', String(clickCount + 1));
40 document.title = `Clicked ${clickCount + 1} times`;
41 }}
42 className="button"
43 >
44 Click me (Web): {clickCount}
45 </button>
46
47 {/* CSS Animations */}
48 <div className="animated-box">
49 CSS animations work natively
50 </div>
51
52 {/* Web-only features */}
53 <iframe
54 src="https://example.com"
55 width="100%"
56 height="300"
57 />
58
59 <input
60 type="file"
61 accept="image/*"
62 onChange={(e) => console.log(e.target.files)}
63 />
64 </div>
65 );
66};
67
68// CSS file (styles.css)
69/*
70.container {
71 max-width: 1200px;
72 margin: 0 auto;
73 padding: 20px;
74}
75
76.card {
77 background: white;
78 border-radius: 8px;
79 box-shadow: 0 2px 8px rgba(0,0,0,0.1);
80 padding: 16px;
81 cursor: pointer;
82}
83
84.card:hover {
85 box-shadow: 0 4px 16px rgba(0,0,0,0.15);
86}
87
88.animated-box {
89 animation: pulse 2s infinite;
90}
91
92@keyframes pulse {
93 0% { opacity: 1; }
94 50% { opacity: 0.5; }
95 100% { opacity: 1; }
96}
97
98@media (max-width: 768px) {
99 .container {
100 padding: 10px;
101 }
102}
103*/

React Native

1// React Native - Native component rendering
2import React, { useState, useRef } from 'react';
3import {
4 View,
5 Text,
6 StyleSheet,
7 TouchableOpacity,
8 Image,
9 ScrollView,
10 Animated,
11 Platform,
12 Dimensions,
13 Alert
14} from 'react-native';
15import AsyncStorage from '@react-native-async-storage/async-storage';
16
17// Native Component using Native elements
18const NativeComponent = () => {
19 const [clickCount, setClickCount] = useState(0);
20 const scaleAnim = useRef(new Animated.Value(1)).current;
21 const { width } = Dimensions.get('window');
22
23 const handlePress = () => {
24 // Haptic feedback (iOS)
25 if (Platform.OS === 'ios') {
26 // Would use react-native-haptic-feedback
27 }
28
29 // Animate
30 Animated.sequence([
31 Animated.timing(scaleAnim, {
32 toValue: 0.95,
33 duration: 100,
34 useNativeDriver: true
35 }),
36 Animated.timing(scaleAnim, {
37 toValue: 1,
38 duration: 100,
39 useNativeDriver: true
40 })
41 ]).start();
42 };
43
44 return (
45 <ScrollView style={styles.container}>
46 <Text style={styles.title}>React Native Application</Text>
47
48 {/* Native Components */}
49 <Animated.View
50 style={[
51 styles.card,
52 { transform: [{ scale: scaleAnim }] }
53 ]}
54 >
55 <Image
56 source={{ uri: 'https://example.com/image.jpg' }}
57 style={styles.cardImage}
58 resizeMode="cover"
59 />
60 <Text style={styles.cardText}>
61 This runs on iOS and Android natively
62 </Text>
63 </Animated.View>
64
65 {/* Native-specific APIs */}
66 <TouchableOpacity
67 onPress={async () => {
68 setClickCount(prev => prev + 1);
69 // Native APIs
70 await AsyncStorage.setItem('clicks', String(clickCount + 1));
71 Alert.alert('Button Pressed', `Clicked ${clickCount + 1} times`);
72 }}
73 style={styles.button}
74 activeOpacity={0.8}
75 >
76 <Text style={styles.buttonText}>
77 Click me (Native): {clickCount}
78 </Text>
79 </TouchableOpacity>
80
81 {/* Platform-specific rendering */}
82 <View style={styles.platformBox}>
83 <Text style={styles.platformText}>
84 Running on {Platform.OS} {Platform.Version}
85 </Text>
86 </View>
87
88 {/* Native-only features */}
89 {Platform.OS === 'ios' && (
90 <Text style={styles.iosOnly}>
91 iOS-specific feature
92 </Text>
93 )}
94 </ScrollView>
95 );
96};
97
98const styles = StyleSheet.create({
99 container: {
100 flex: 1,
101 backgroundColor: '#f5f5f5'
102 },
103 title: {
104 fontSize: 24,
105 fontWeight: 'bold',
106 textAlign: 'center',
107 marginVertical: 20,
108 color: '#333'
109 },
110 card: {
111 backgroundColor: 'white',
112 borderRadius: 8,
113 padding: 16,
114 marginHorizontal: 20,
115 marginVertical: 10,
116 // React Native shadow
117 ...Platform.select({
118 ios: {
119 shadowColor: '#000',
120 shadowOffset: { width: 0, height: 2 },
121 shadowOpacity: 0.1,
122 shadowRadius: 4
123 },
124 android: {
125 elevation: 4
126 }
127 })
128 },
129 cardImage: {
130 width: '100%',
131 height: 200,
132 borderRadius: 8,
133 marginBottom: 10
134 },
135 button: {
136 backgroundColor: '#007AFF',
137 paddingHorizontal: 20,
138 paddingVertical: 12,
139 borderRadius: 8,
140 marginHorizontal: 20,
141 alignItems: 'center'
142 },
143 buttonText: {
144 color: 'white',
145 fontSize: 16,
146 fontWeight: '600'
147 },
148 platformBox: {
149 backgroundColor: '#e0e0e0',
150 padding: 10,
151 margin: 20,
152 borderRadius: 4
153 }
154});

Component & Styling Differences

Compare component APIs and styling approaches between platforms

React Web uses HTML elements with CSS, while React Native uses platform-specific components with StyleSheet API. Understanding these differences is crucial for cross-platform development.

// Component Comparison Table
| Feature | React Web | React Native |
|---------|-----------|--------------|
| Container | <div> | <View> |
| Text | <p>, <span>, <h1> | <Text> |
| Image | <img> | <Image> |
| Button | <button> | <TouchableOpacity>, <Button> |
| Input | <input> | <TextInput> |
| List | <ul>, <ol> | <FlatList>, <SectionList> |
| Scroll | CSS overflow | <ScrollView> |
| Link | <a> | <Link> (React Navigation) |

React Web

1// React Web - Rich styling with CSS
2import React from 'react';
3import styled from 'styled-components';
4
5// Styled Components
6const Container = styled.div`
7 display: flex;
8 flex-direction: column;
9 align-items: center;
10 padding: 2rem;
11 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
12 min-height: 100vh;
13`;
14
15const Card = styled.div`
16 background: white;
17 border-radius: 12px;
18 padding: 2rem;
19 box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
20 transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
21
22 &:hover {
23 transform: translateY(-5px);
24 box-shadow: 0 15px 40px rgba(0, 0, 0, 0.25);
25 }
26
27 @media (max-width: 768px) {
28 padding: 1rem;
29 width: 90%;
30 }
31`;
32
33const GradientButton = styled.button`
34 background: linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%);
35 border: none;
36 border-radius: 3px;
37 color: white;
38 padding: 0.75rem 2rem;
39 font-size: 1rem;
40 font-weight: bold;
41 cursor: pointer;
42 position: relative;
43 overflow: hidden;
44
45 &::before {
46 content: '';
47 position: absolute;
48 top: 0;
49 left: -100%;
50 width: 100%;
51 height: 100%;
52 background: rgba(255, 255, 255, 0.2);
53 transition: left 0.5s;
54 }
55
56 &:hover::before {
57 left: 100%;
58 }
59`;
60
61// Complex animations with CSS
62const AnimatedLogo = styled.div`
63 width: 100px;
64 height: 100px;
65 background: url('/logo.svg') center/contain no-repeat;
66 animation: spin 3s linear infinite;
67
68 @keyframes spin {
69 from { transform: rotate(0deg); }
70 to { transform: rotate(360deg); }
71 }
72`;
73
74// Grid Layout
75const GridContainer = styled.div`
76 display: grid;
77 grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
78 gap: 2rem;
79 width: 100%;
80 max-width: 1200px;
81
82 @supports (display: grid) {
83 .grid-item {
84 grid-column: span 1;
85 }
86
87 .grid-item.featured {
88 grid-column: span 2;
89 grid-row: span 2;
90 }
91 }
92`;
93
94const WebStylingExample = () => {
95 return (
96 <Container>
97 <AnimatedLogo />
98
99 <Card>
100 <h2>Advanced CSS Features</h2>
101 <ul>
102 <li>CSS Grid & Flexbox</li>
103 <li>CSS Variables</li>
104 <li>Complex animations</li>
105 <li>Pseudo-elements</li>
106 <li>Media queries</li>
107 <li>Hover effects</li>
108 </ul>
109
110 <GradientButton>
111 Hover for effect
112 </GradientButton>
113 </Card>
114
115 <GridContainer>
116 <div className="grid-item">Item 1</div>
117 <div className="grid-item featured">Featured</div>
118 <div className="grid-item">Item 3</div>
119 </GridContainer>
120 </Container>
121 );
122};

React Native

1// React Native - StyleSheet API
2import React from 'react';
3import {
4 View,
5 Text,
6 StyleSheet,
7 TouchableOpacity,
8 Animated,
9 Easing,
10 Dimensions,
11 Platform
12} from 'react-native';
13import LinearGradient from 'react-native-linear-gradient';
14
15const { width } = Dimensions.get('window');
16
17const NativeStylingExample = () => {
18 const spinValue = new Animated.Value(0);
19
20 // Spin animation
21 Animated.loop(
22 Animated.timing(spinValue, {
23 toValue: 1,
24 duration: 3000,
25 easing: Easing.linear,
26 useNativeDriver: true
27 })
28 ).start();
29
30 const spin = spinValue.interpolate({
31 inputRange: [0, 1],
32 outputRange: ['0deg', '360deg']
33 });
34
35 return (
36 <LinearGradient
37 colors={['#667eea', '#764ba2']}
38 style={styles.container}
39 >
40 <Animated.View
41 style={[
42 styles.animatedLogo,
43 { transform: [{ rotate: spin }] }
44 ]}
45 />
46
47 <View style={styles.card}>
48 <Text style={styles.title}>React Native Styling</Text>
49
50 <View style={styles.list}>
51 <Text style={styles.listItem}>Flexbox layout (default)</Text>
52 <Text style={styles.listItem}>StyleSheet API</Text>
53 <Text style={styles.listItem}>Animated API</Text>
54 <Text style={styles.listItem}>Platform-specific styles</Text>
55 <Text style={styles.listItem}>Limited styling options</Text>
56 <Text style={styles.listItem}>No hover effects</Text>
57 </View>
58
59 <TouchableOpacity activeOpacity={0.8}>
60 <LinearGradient
61 colors={['#FE6B8B', '#FF8E53']}
62 start={{ x: 0, y: 0 }}
63 end={{ x: 1, y: 1 }}
64 style={styles.gradientButton}
65 >
66 <Text style={styles.buttonText}>Press me</Text>
67 </LinearGradient>
68 </TouchableOpacity>
69 </View>
70
71 {/* Flexbox Grid Alternative */}
72 <View style={styles.grid}>
73 <View style={styles.gridItem}>
74 <Text>Item 1</Text>
75 </View>
76 <View style={[styles.gridItem, styles.featuredItem]}>
77 <Text>Featured</Text>
78 </View>
79 <View style={styles.gridItem}>
80 <Text>Item 3</Text>
81 </View>
82 </View>
83 </LinearGradient>
84 );
85};
86
87const styles = StyleSheet.create({
88 container: {
89 flex: 1,
90 alignItems: 'center',
91 padding: 20
92 },
93 animatedLogo: {
94 width: 100,
95 height: 100,
96 backgroundColor: 'white',
97 borderRadius: 50
98 },
99 card: {
100 backgroundColor: 'white',
101 borderRadius: 12,
102 padding: 20,
103 marginTop: 20,
104 width: width - 40,
105 ...Platform.select({
106 ios: {
107 shadowColor: '#000',
108 shadowOffset: { width: 0, height: 10 },
109 shadowOpacity: 0.2,
110 shadowRadius: 15
111 },
112 android: {
113 elevation: 10
114 }
115 })
116 },
117 title: {
118 fontSize: 24,
119 fontWeight: 'bold',
120 marginBottom: 15,
121 textAlign: 'center'
122 },
123 list: {
124 marginBottom: 20
125 },
126 listItem: {
127 fontSize: 16,
128 marginVertical: 5,
129 color: '#333'
130 },
131 gradientButton: {
132 paddingVertical: 12,
133 paddingHorizontal: 30,
134 borderRadius: 25,
135 alignItems: 'center'
136 },
137 buttonText: {
138 color: 'white',
139 fontSize: 16,
140 fontWeight: 'bold'
141 },
142 grid: {
143 flexDirection: 'row',
144 flexWrap: 'wrap',
145 marginTop: 20,
146 width: width - 40,
147 justifyContent: 'space-between'
148 },
149 gridItem: {
150 backgroundColor: 'white',
151 padding: 20,
152 borderRadius: 8,
153 width: (width - 60) / 2 - 5,
154 marginBottom: 10,
155 alignItems: 'center'
156 },
157 featuredItem: {
158 width: width - 40
159 }
160});

Navigation Patterns

Compare navigation implementations between web and mobile platforms

Navigation is handled very differently between React Web and React Native. Web uses URLs and browser history, while Native uses stack-based navigation with gestures.

React Web

1// React Web - React Router
2import React from 'react';
3import {
4 BrowserRouter as Router,
5 Routes,
6 Route,
7 Link,
8 useNavigate,
9 useLocation,
10 useParams,
11 Navigate,
12 Outlet
13} from 'react-router-dom';
14
15// Layout Component
16const Layout = () => {
17 const location = useLocation();
18
19 return (
20 <div className="app-layout">
21 <nav className="navbar">
22 <Link to="/" className="nav-link">
23 Home
24 </Link>
25 <Link to="/products" className="nav-link">
26 Products
27 </Link>
28 <Link to="/profile" className="nav-link">
29 Profile
30 </Link>
31 </nav>
32
33 {/* Breadcrumbs */}
34 <div className="breadcrumbs">
35 {location.pathname.split('/').filter(Boolean).map((path, index) => (
36 <span key={path}>
37 {index > 0 && ' > '}
38 <Link to={`/${path}`}>{path}</Link>
39 </span>
40 ))}
41 </div>
42
43 <main className="main-content">
44 <Outlet />
45 </main>
46 </div>
47 );
48};
49
50// Protected Route
51const ProtectedRoute = ({ children }) => {
52 const isAuthenticated = useAuth();
53 const location = useLocation();
54
55 if (!isAuthenticated) {
56 return <Navigate to="/login" state={{ from: location }} replace />;
57 }
58
59 return children;
60};
61
62// Product Detail Page
63const ProductDetail = () => {
64 const { id } = useParams();
65 const navigate = useNavigate();
66 const location = useLocation();
67
68 return (
69 <div>
70 <button onClick={() => navigate(-1)}>
71Back
72 </button>
73
74 <h1>Product {id}</h1>
75
76 {/* Query params */}
77 <p>Current filter: {new URLSearchParams(location.search).get('filter')}</p>
78
79 {/* Programmatic navigation */}
80 <button onClick={() => navigate('/products', { replace: true })}>
81 All Products
82 </button>
83
84 {/* Navigate with state */}
85 <button onClick={() => navigate('/checkout', {
86 state: { productId: id }
87 })}>
88 Buy Now
89 </button>
90 </div>
91 );
92};
93
94// App with routing
95const WebApp = () => {
96 return (
97 <Router>
98 <Routes>
99 <Route path="/" element={<Layout />}>
100 <Route index element={<Home />} />
101 <Route path="products">
102 <Route index element={<Products />} />
103 <Route path=":id" element={<ProductDetail />} />
104 </Route>
105 <Route
106 path="profile"
107 element={
108 <ProtectedRoute>
109 <Profile />
110 </ProtectedRoute>
111 }
112 />
113 <Route path="login" element={<Login />} />
114 <Route path="*" element={<NotFound />} />
115 </Route>
116 </Routes>
117 </Router>
118 );
119};
120
121// Deep linking with URL
122// https://app.com/products/123?filter=electronics
123// Automatically handled by React Router

React Native

1// React Native - React Navigation
2import React from 'react';
3import {
4 NavigationContainer,
5 useNavigation,
6 useRoute,
7 useFocusEffect,
8 DrawerActions
9} from '@react-navigation/native';
10import { createNativeStackNavigator } from '@react-navigation/native-stack';
11import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
12import { createDrawerNavigator } from '@react-navigation/drawer';
13import {
14 View,
15 Text,
16 TouchableOpacity,
17 Platform
18} from 'react-native';
19import Icon from 'react-native-vector-icons/Ionicons';
20
21// Type definitions
22type RootStackParamList = {
23 Home: undefined;
24 Products: { category?: string };
25 ProductDetail: { id: string };
26 Profile: undefined;
27 Login: { from?: string };
28};
29
30const Stack = createNativeStackNavigator<RootStackParamList>();
31const Tab = createBottomTabNavigator();
32const Drawer = createDrawerNavigator();
33
34// Product Detail Screen
35const ProductDetailScreen = () => {
36 const navigation = useNavigation();
37 const route = useRoute();
38 const { id } = route.params;
39
40 // Focus effect (like useEffect but for navigation)
41 useFocusEffect(
42 React.useCallback(() => {
43 console.log('Screen focused');
44 return () => console.log('Screen unfocused');
45 }, [])
46 );
47
48 return (
49 <View style={styles.container}>
50 {/* Native back gesture on iOS, button on Android */}
51 <TouchableOpacity
52 onPress={() => navigation.goBack()}
53 style={styles.backButton}
54 >
55 <Icon name="arrow-back" size={24} />
56 <Text>Back</Text>
57 </TouchableOpacity>
58
59 <Text style={styles.title}>Product {id}</Text>
60
61 {/* Navigate with params */}
62 <TouchableOpacity
63 onPress={() =>
64 navigation.navigate('Products', { category: 'electronics' })
65 }
66 style={styles.button}
67 >
68 <Text>View Electronics</Text>
69 </TouchableOpacity>
70
71 {/* Reset navigation stack */}
72 <TouchableOpacity
73 onPress={() =>
74 navigation.reset({
75 index: 0,
76 routes: [{ name: 'Home' }],
77 })
78 }
79 style={styles.button}
80 >
81 <Text>Go to Home (Reset Stack)</Text>
82 </TouchableOpacity>
83 </View>
84 );
85};
86
87// Tab Navigator
88const TabNavigator = () => {
89 return (
90 <Tab.Navigator
91 screenOptions={({ route }) => ({
92 tabBarIcon: ({ focused, color, size }) => {
93 let iconName;
94
95 if (route.name === 'Home') {
96 iconName = focused ? 'home' : 'home-outline';
97 } else if (route.name === 'Products') {
98 iconName = focused ? 'grid' : 'grid-outline';
99 } else if (route.name === 'Profile') {
100 iconName = focused ? 'person' : 'person-outline';
101 }
102
103 return <Icon name={iconName} size={size} color={color} />;
104 },
105 tabBarActiveTintColor: '#007AFF',
106 tabBarInactiveTintColor: 'gray',
107 // Platform-specific styling
108 tabBarStyle: Platform.select({
109 ios: {
110 backgroundColor: 'white',
111 },
112 android: {
113 backgroundColor: '#f8f8f8',
114 elevation: 8,
115 },
116 }),
117 })}
118 >
119 <Tab.Screen name="Home" component={HomeScreen} />
120 <Tab.Screen name="Products" component={ProductsStack} />
121 <Tab.Screen name="Profile" component={ProfileScreen} />
122 </Tab.Navigator>
123 );
124};
125
126// Drawer Navigator (typically for tablets or specific UX)
127const DrawerNavigator = () => {
128 const navigation = useNavigation();
129
130 return (
131 <Drawer.Navigator
132 screenOptions={{
133 drawerStyle: {
134 backgroundColor: '#f5f5f5',
135 width: 240,
136 },
137 headerLeft: () => (
138 <TouchableOpacity
139 onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
140 style={{ marginLeft: 15 }}
141 >
142 <Icon name="menu" size={24} />
143 </TouchableOpacity>
144 ),
145 }}
146 >
147 <Drawer.Screen name="Main" component={TabNavigator} />
148 <Drawer.Screen name="Settings" component={SettingsScreen} />
149 <Drawer.Screen name="About" component={AboutScreen} />
150 </Drawer.Navigator>
151 );
152};
153
154// Main App with deep linking
155const linking = {
156 prefixes: ['myapp://', 'https://myapp.com'],
157 config: {
158 screens: {
159 Home: '',
160 Products: 'products',
161 ProductDetail: 'products/:id',
162 Profile: 'profile',
163 Login: 'login',
164 },
165 },
166};
167
168const NativeApp = () => {
169 return (
170 <NavigationContainer linking={linking}>
171 <Stack.Navigator
172 screenOptions={{
173 // iOS-style navigation
174 headerStyle: {
175 backgroundColor: Platform.OS === 'ios' ? 'white' : '#f5f5f5',
176 },
177 headerShadowVisible: false,
178 // Enable gestures
179 gestureEnabled: true,
180 // Custom animation
181 animation: Platform.OS === 'ios' ? 'slide_from_right' : 'fade',
182 }}
183 >
184 <Stack.Screen
185 name="Main"
186 component={DrawerNavigator}
187 options={{ headerShown: false }}
188 />
189 <Stack.Screen
190 name="ProductDetail"
191 component={ProductDetailScreen}
192 options={({ route }) => ({
193 title: `Product ${route.params.id}`,
194 // iOS back button customization
195 headerBackTitle: 'Back',
196 })}
197 />
198 <Stack.Screen
199 name="Login"
200 component={LoginScreen}
201 options={{
202 // Modal presentation on iOS
203 presentation: 'modal',
204 }}
205 />
206 </Stack.Navigator>
207 </NavigationContainer>
208 );
209};
210
211// Deep linking example:
212// myapp://products/123
213// Opens ProductDetailScreen with id: '123'

Performance & Optimization

Platform-specific performance considerations and optimization techniques

React Web and React Native have different performance characteristics and optimization strategies. Understanding these differences is key to building performant applications.

React Web

1// React Web Performance Optimization
2import React, { lazy, Suspense, useMemo, useCallback, memo } from 'react';
3import { ErrorBoundary } from 'react-error-boundary';
4
5// Code Splitting with lazy loading
6const HeavyComponent = lazy(() =>
7 import(/* webpackChunkName: "heavy" */ './HeavyComponent')
8);
9
10const ProductGallery = lazy(() =>
11 import(/* webpackChunkName: "gallery" */ './ProductGallery')
12);
13
14// Image optimization
15const OptimizedImage = ({ src, alt, ...props }) => {
16 return (
17 <picture>
18 <source
19 srcSet={`${src}.webp`}
20 type="image/webp"
21 />
22 <source
23 srcSet={`${src}.jpg`}
24 type="image/jpeg"
25 />
26 <img
27 src={`${src}.jpg`}
28 alt={alt}
29 loading="lazy"
30 decoding="async"
31 {...props}
32 />
33 </picture>
34 );
35};
36
37// Virtual scrolling for large lists
38import { FixedSizeList as List } from 'react-window';
39
40const VirtualList = ({ items }) => {
41 const Row = memo(({ index, style }) => (
42 <div style={style}>
43 Item {items[index].name}
44 </div>
45 ));
46
47 return (
48 <List
49 height={600}
50 itemCount={items.length}
51 itemSize={50}
52 width="100%"
53 >
54 {Row}
55 </List>
56 );
57};
58
59// Service Worker for offline caching
60// serviceWorker.js
61self.addEventListener('install', (event) => {
62 event.waitUntil(
63 caches.open('v1').then((cache) => {
64 return cache.addAll([
65 '/',
66 '/static/css/main.css',
67 '/static/js/bundle.js',
68 '/offline.html'
69 ]);
70 })
71 );
72});
73
74// CSS optimization
75const CriticalCSS = () => {
76 return (
77 <>
78 {/* Critical CSS inlined */}
79 <style dangerouslySetInnerHTML={{ __html: `
80 .above-fold {
81 display: flex;
82 min-height: 100vh;
83 }
84 .hero-text {
85 font-size: 3rem;
86 font-weight: bold;
87 }
88 ` }} />
89
90 {/* Non-critical CSS loaded async */}
91 <link
92 rel="preload"
93 href="/styles/main.css"
94 as="style"
95 onLoad="this.onload=null;this.rel='stylesheet'"
96 />
97 </>
98 );
99};
100
101// Web Vitals monitoring
102import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
103
104function sendToAnalytics(metric) {
105 const body = JSON.stringify(metric);
106 // Use `navigator.sendBeacon()` if available, falling back to `fetch()`
107 (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
108 fetch('/analytics', { body, method: 'POST', keepalive: true });
109}
110
111getCLS(sendToAnalytics);
112getFID(sendToAnalytics);
113getFCP(sendToAnalytics);
114getLCP(sendToAnalytics);
115getTTFB(sendToAnalytics);
116
117// Memoization example
118const ExpensiveComponent = memo(({ data, filter }) => {
119 const filteredData = useMemo(() =>
120 data.filter(item => item.category === filter),
121 [data, filter]
122 );
123
124 const handleClick = useCallback((id) => {
125 console.log('Clicked:', id);
126 }, []);
127
128 return (
129 <div>
130 {filteredData.map(item => (
131 <div key={item.id} onClick={() => handleClick(item.id)}>
132 {item.name}
133 </div>
134 ))}
135 </div>
136 );
137});
138
139// Bundle optimization with webpack
140// webpack.config.js
141module.exports = {
142 optimization: {
143 splitChunks: {
144 chunks: 'all',
145 cacheGroups: {
146 vendor: {
147 test: /[\/]node_modules[\/]/,
148 name: 'vendors',
149 priority: 10
150 },
151 common: {
152 minChunks: 2,
153 priority: 5,
154 reuseExistingChunk: true
155 }
156 }
157 },
158 // Tree shaking
159 usedExports: true,
160 // Minification
161 minimize: true,
162 // Module concatenation
163 concatenateModules: true
164 }
165};

React Native

1// React Native Performance Optimization
2import React, { memo, useMemo, useCallback } from 'react';
3import {
4 FlatList,
5 View,
6 Text,
7 Image,
8 InteractionManager,
9 Platform
10} from 'react-native';
11import FastImage from 'react-native-fast-image';
12
13// Optimized Image Component
14const OptimizedImage = ({ source, style }) => {
15 return (
16 <FastImage
17 source={{
18 uri: source,
19 priority: FastImage.priority.normal,
20 cache: FastImage.cacheControl.immutable,
21 }}
22 style={style}
23 resizeMode={FastImage.resizeMode.cover}
24 />
25 );
26};
27
28// FlatList optimization for large lists
29const OptimizedList = ({ data }) => {
30 // Memoized render item
31 const renderItem = useCallback(({ item }) => (
32 <ProductItem product={item} />
33 ), []);
34
35 // Key extractor
36 const keyExtractor = useCallback((item) => item.id.toString(), []);
37
38 // Get item layout for better performance
39 const getItemLayout = useCallback((data, index) => ({
40 length: ITEM_HEIGHT,
41 offset: ITEM_HEIGHT * index,
42 index,
43 }), []);
44
45 return (
46 <FlatList
47 data={data}
48 renderItem={renderItem}
49 keyExtractor={keyExtractor}
50 getItemLayout={getItemLayout}
51
52 // Performance optimizations
53 removeClippedSubviews={true}
54 maxToRenderPerBatch={10}
55 updateCellsBatchingPeriod={50}
56 initialNumToRender={10}
57 windowSize={10}
58
59 // Memory optimization
60 onEndReachedThreshold={0.5}
61 onEndReached={loadMore}
62
63 // Scroll performance
64 scrollEventThrottle={16}
65
66 // Android specific
67 overScrollMode="never"
68
69 // iOS specific
70 directionalLockEnabled={true}
71 />
72 );
73};
74
75// Memoized component
76const ProductItem = memo(({ product }) => {
77 return (
78 <View style={styles.item}>
79 <OptimizedImage
80 source={product.image}
81 style={styles.image}
82 />
83 <Text style={styles.title}>{product.name}</Text>
84 <Text style={styles.price}>${product.price}</Text>
85 </View>
86 );
87}, (prevProps, nextProps) => {
88 // Custom comparison
89 return prevProps.product.id === nextProps.product.id &&
90 prevProps.product.price === nextProps.product.price;
91});
92
93// InteractionManager for heavy operations
94const HeavyOperationComponent = () => {
95 const [data, setData] = useState(null);
96
97 useEffect(() => {
98 // Defer heavy computation after interactions
99 InteractionManager.runAfterInteractions(() => {
100 const processedData = heavyDataProcessing(rawData);
101 setData(processedData);
102 });
103 }, []);
104
105 return data ? <DataDisplay data={data} /> : <Loading />;
106};
107
108// Native performance monitoring
109import Perf from 'react-native-performance';
110
111// Monitor app startup time
112Perf.mark('appStart');
113// ... app initialization
114Perf.measure('startupTime', 'appStart');
115
116// Monitor navigation transitions
117const NavigationPerformance = () => {
118 const navigation = useNavigation();
119
120 React.useEffect(() => {
121 const unsubscribe = navigation.addListener('transitionStart', (e) => {
122 Perf.mark(`nav_start_${e.data.closing}`);
123 });
124
125 const unsubscribeEnd = navigation.addListener('transitionEnd', (e) => {
126 Perf.measure(
127 `navigation_${e.data.closing}`,
128 `nav_start_${e.data.closing}`
129 );
130 });
131
132 return () => {
133 unsubscribe();
134 unsubscribeEnd();
135 };
136 }, [navigation]);
137};
138
139// RAM bundle optimization (Android)
140// metro.config.js
141module.exports = {
142 transformer: {
143 minifierConfig: {
144 keep_fnames: true,
145 mangle: {
146 keep_fnames: true,
147 },
148 },
149 },
150 serializer: {
151 createModuleIdFactory: () => {
152 return (path) => {
153 // Custom module ID for better RAM bundle
154 return path.replace(/^.*[/\]/, '');
155 };
156 },
157 },
158};
159
160// Hermes optimization (Android)
161// android/app/build.gradle
162android {
163 ...
164 packagingOptions {
165 // Use Hermes engine
166 pickFirst '**/libjsc.so'
167 pickFirst '**/libc++_shared.so'
168 }
169}
170
171// Memory optimization
172const MemoryOptimizedComponent = () => {
173 // Clean up timers
174 useEffect(() => {
175 const timer = setTimeout(() => {
176 // Do something
177 }, 1000);
178
179 return () => clearTimeout(timer);
180 }, []);
181
182 // Clean up event listeners
183 useEffect(() => {
184 const subscription = DeviceEventEmitter.addListener(
185 'event',
186 handleEvent
187 );
188
189 return () => subscription.remove();
190 }, []);
191
192 // Nullify large objects
193 useEffect(() => {
194 return () => {
195 largeDataRef.current = null;
196 };
197 }, []);
198};

Platform-Specific Features

Leverage unique capabilities of each platform

Each platform offers unique features and APIs. React Web has access to all browser APIs, while React Native can access device hardware and native platform features.

React Web

1// React Web - Browser-specific features
2import React, { useState, useEffect } from 'react';
3
4// Progressive Web App features
5const WebFeatures = () => {
6 const [location, setLocation] = useState(null);
7 const [notification, setNotification] = useState('');
8 const [online, setOnline] = useState(navigator.onLine);
9
10 // Geolocation API
11 const getLocation = () => {
12 if ('geolocation' in navigator) {
13 navigator.geolocation.getCurrentPosition(
14 (position) => {
15 setLocation({
16 lat: position.coords.latitude,
17 lng: position.coords.longitude
18 });
19 },
20 (error) => console.error('Location error:', error),
21 { enableHighAccuracy: true }
22 );
23 }
24 };
25
26 // Notification API
27 const sendNotification = async () => {
28 if ('Notification' in window) {
29 const permission = await Notification.requestPermission();
30 if (permission === 'granted') {
31 new Notification('Hello from React Web!', {
32 body: 'This is a web notification',
33 icon: '/icon-192.png',
34 badge: '/badge-72.png',
35 vibrate: [200, 100, 200]
36 });
37 }
38 }
39 };
40
41 // Online/Offline detection
42 useEffect(() => {
43 const handleOnline = () => setOnline(true);
44 const handleOffline = () => setOnline(false);
45
46 window.addEventListener('online', handleOnline);
47 window.addEventListener('offline', handleOffline);
48
49 return () => {
50 window.removeEventListener('online', handleOnline);
51 window.removeEventListener('offline', handleOffline);
52 };
53 }, []);
54
55 // Web Share API
56 const shareContent = async () => {
57 if (navigator.share) {
58 try {
59 await navigator.share({
60 title: 'Check this out!',
61 text: 'Amazing React Web features',
62 url: window.location.href
63 });
64 } catch (error) {
65 console.error('Share failed:', error);
66 }
67 }
68 };
69
70 // Payment Request API
71 const makePayment = async () => {
72 if (window.PaymentRequest) {
73 const supportedMethods = [{
74 supportedMethods: 'basic-card',
75 data: {
76 supportedNetworks: ['visa', 'mastercard'],
77 supportedTypes: ['debit', 'credit']
78 }
79 }];
80
81 const details = {
82 total: {
83 label: 'Total',
84 amount: { currency: 'USD', value: '10.00' }
85 }
86 };
87
88 const request = new PaymentRequest(supportedMethods, details);
89 try {
90 const result = await request.show();
91 console.log('Payment successful:', result);
92 } catch (error) {
93 console.error('Payment failed:', error);
94 }
95 }
96 };
97
98 // File System Access API
99 const saveFile = async () => {
100 if ('showSaveFilePicker' in window) {
101 try {
102 const handle = await window.showSaveFilePicker({
103 suggestedName: 'data.json',
104 types: [{
105 description: 'JSON Files',
106 accept: { 'application/json': ['.json'] }
107 }]
108 });
109
110 const writable = await handle.createWritable();
111 await writable.write(JSON.stringify({ data: 'example' }));
112 await writable.close();
113 } catch (error) {
114 console.error('Save failed:', error);
115 }
116 }
117 };
118
119 // WebRTC for video calls
120 const startVideoCall = async () => {
121 try {
122 const stream = await navigator.mediaDevices.getUserMedia({
123 video: true,
124 audio: true
125 });
126
127 const videoElement = document.getElementById('localVideo');
128 videoElement.srcObject = stream;
129 } catch (error) {
130 console.error('Media access failed:', error);
131 }
132 };
133
134 // Web Speech API
135 const speakText = (text) => {
136 if ('speechSynthesis' in window) {
137 const utterance = new SpeechSynthesisUtterance(text);
138 utterance.lang = 'en-US';
139 utterance.rate = 1.0;
140 speechSynthesis.speak(utterance);
141 }
142 };
143
144 return (
145 <div className="web-features">
146 <h2>Web Platform Features</h2>
147
148 <div className="feature-grid">
149 <button onClick={getLocation}>
150 Get Location {location && `(${location.lat}, ${location.lng})`}
151 </button>
152
153 <button onClick={sendNotification}>
154 Send Notification
155 </button>
156
157 <button onClick={shareContent}>
158 Share Content
159 </button>
160
161 <button onClick={makePayment}>
162 Make Payment
163 </button>
164
165 <button onClick={saveFile}>
166 Save File
167 </button>
168
169 <button onClick={startVideoCall}>
170 Start Video
171 </button>
172
173 <button onClick={() => speakText('Hello from React Web!')}>
174 Speak Text
175 </button>
176 </div>
177
178 <p>Network Status: {online ? '🟢 Online' : '🔴 Offline'}</p>
179
180 <video id="localVideo" autoPlay muted />
181
182 {/* Drag and Drop */}
183 <div
184 onDragOver={(e) => e.preventDefault()}
185 onDrop={(e) => {
186 e.preventDefault();
187 const files = Array.from(e.dataTransfer.files);
188 console.log('Dropped files:', files);
189 }}
190 className="drop-zone"
191 >
192 Drop files here
193 </div>
194 </div>
195 );
196};

React Native

1// React Native - Native platform features
2import React, { useState, useEffect } from 'react';
3import {
4 View,
5 Text,
6 TouchableOpacity,
7 Alert,
8 Platform,
9 Vibration
10} from 'react-native';
11import * as Location from 'expo-location';
12import * as Notifications from 'expo-notifications';
13import * as Camera from 'expo-camera';
14import * as Contacts from 'expo-contacts';
15import * as Battery from 'expo-battery';
16import * as Haptics from 'expo-haptics';
17import { Accelerometer, Gyroscope } from 'expo-sensors';
18import * as LocalAuthentication from 'expo-local-authentication';
19import * as StoreReview from 'expo-store-review';
20import NetInfo from '@react-native-community/netinfo';
21
22const NativeFeatures = () => {
23 const [location, setLocation] = useState(null);
24 const [batteryLevel, setBatteryLevel] = useState(null);
25 const [accelerometerData, setAccelerometerData] = useState({});
26 const [isConnected, setIsConnected] = useState(true);
27
28 // Location Services
29 const getLocation = async () => {
30 const { status } = await Location.requestForegroundPermissionsAsync();
31 if (status !== 'granted') {
32 Alert.alert('Permission denied');
33 return;
34 }
35
36 const location = await Location.getCurrentPositionAsync({
37 accuracy: Location.Accuracy.High
38 });
39 setLocation(location.coords);
40
41 // Background location tracking
42 await Location.startLocationUpdatesAsync('background-location-task', {
43 accuracy: Location.Accuracy.Balanced,
44 timeInterval: 10000,
45 distanceInterval: 10
46 });
47 };
48
49 // Push Notifications
50 const sendNotification = async () => {
51 const { status } = await Notifications.requestPermissionsAsync();
52 if (status !== 'granted') return;
53
54 await Notifications.scheduleNotificationAsync({
55 content: {
56 title: 'React Native Notification',
57 body: 'This is a local notification!',
58 data: { data: 'goes here' },
59 sound: true,
60 badge: 1
61 },
62 trigger: { seconds: 2 }
63 });
64 };
65
66 // Camera Access
67 const takePhoto = async () => {
68 const { status } = await Camera.requestCameraPermissionsAsync();
69 if (status !== 'granted') return;
70
71 // Navigate to camera screen
72 // Implementation depends on navigation setup
73 };
74
75 // Contacts Access
76 const getContacts = async () => {
77 const { status } = await Contacts.requestPermissionsAsync();
78 if (status !== 'granted') return;
79
80 const { data } = await Contacts.getContactsAsync({
81 fields: [Contacts.Fields.Emails, Contacts.Fields.PhoneNumbers]
82 });
83
84 console.log('Contacts:', data.length);
85 };
86
87 // Biometric Authentication
88 const authenticate = async () => {
89 const hasHardware = await LocalAuthentication.hasHardwareAsync();
90 if (!hasHardware) {
91 Alert.alert('No biometric hardware');
92 return;
93 }
94
95 const result = await LocalAuthentication.authenticateAsync({
96 promptMessage: 'Authenticate to continue',
97 disableDeviceFallback: false,
98 cancelLabel: 'Cancel'
99 });
100
101 if (result.success) {
102 Alert.alert('Authentication successful!');
103 }
104 };
105
106 // Device Sensors
107 useEffect(() => {
108 // Battery monitoring
109 Battery.getBatteryLevelAsync().then(setBatteryLevel);
110 const batterySubscription = Battery.addBatteryLevelListener(({ batteryLevel }) => {
111 setBatteryLevel(batteryLevel);
112 });
113
114 // Accelerometer
115 Accelerometer.setUpdateInterval(100);
116 const accelSubscription = Accelerometer.addListener(setAccelerometerData);
117
118 // Network monitoring
119 const netInfoSubscription = NetInfo.addEventListener(state => {
120 setIsConnected(state.isConnected);
121 });
122
123 return () => {
124 batterySubscription.remove();
125 accelSubscription.remove();
126 netInfoSubscription();
127 };
128 }, []);
129
130 // Haptic Feedback
131 const triggerHaptic = async (type) => {
132 switch (type) {
133 case 'light':
134 await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
135 break;
136 case 'medium':
137 await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
138 break;
139 case 'heavy':
140 await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy);
141 break;
142 case 'selection':
143 await Haptics.selectionAsync();
144 break;
145 case 'notification':
146 await Haptics.notificationAsync(
147 Haptics.NotificationFeedbackType.Success
148 );
149 break;
150 }
151 };
152
153 // Platform-specific features
154 const platformSpecific = () => {
155 if (Platform.OS === 'ios') {
156 // iOS specific - Request app store review
157 if (StoreReview.isAvailableAsync()) {
158 StoreReview.requestReview();
159 }
160 } else if (Platform.OS === 'android') {
161 // Android specific - Long vibration pattern
162 Vibration.vibrate([0, 500, 200, 500]);
163 }
164 };
165
166 return (
167 <View style={styles.container}>
168 <Text style={styles.title}>Native Platform Features</Text>
169
170 <TouchableOpacity
171 style={styles.button}
172 onPress={getLocation}
173 >
174 <Text>Get Location</Text>
175 {location && (
176 <Text>{location.latitude}, {location.longitude}</Text>
177 )}
178 </TouchableOpacity>
179
180 <TouchableOpacity
181 style={styles.button}
182 onPress={sendNotification}
183 >
184 <Text>Send Notification</Text>
185 </TouchableOpacity>
186
187 <TouchableOpacity
188 style={styles.button}
189 onPress={authenticate}
190 >
191 <Text>Biometric Auth</Text>
192 </TouchableOpacity>
193
194 <TouchableOpacity
195 style={styles.button}
196 onPress={() => triggerHaptic('medium')}
197 >
198 <Text>Haptic Feedback</Text>
199 </TouchableOpacity>
200
201 <View style={styles.info}>
202 <Text>Battery: {batteryLevel ? `${(batteryLevel * 100).toFixed(0)}%` : 'N/A'}</Text>
203 <Text>Network: {isConnected ? '🟢 Connected' : '🔴 Disconnected'}</Text>
204 <Text>Accelerometer X: {accelerometerData.x?.toFixed(2)}</Text>
205 </View>
206 </View>
207 );
208};

Advertisement Space - mid-comparison

Google AdSense: rectangle

When to Use Each Platform

Use React Web When:

  • Building websites or web applications
  • SEO is important
  • Need instant updates without app store approval
  • Broader reach across all devices
  • Complex layouts and styling requirements

Use React Native When:

  • Building mobile apps for iOS and Android
  • Need access to device features (camera, GPS, etc.)
  • Want native performance and feel
  • Need offline functionality
  • Want to distribute through app stores

Code Sharing Strategies

Shared Code Architecture

1// Shared business logic
2// packages/shared/src/hooks/useAuth.ts
3export const useAuth = () => {
4 const [user, setUser] = useState(null);
5 const [loading, setLoading] = useState(true);
6
7 const login = async (credentials) => {
8 // Shared authentication logic
9 const response = await api.login(credentials);
10 setUser(response.user);
11 return response;
12 };
13
14 const logout = async () => {
15 await api.logout();
16 setUser(null);
17 };
18
19 return { user, loading, login, logout };
20};
21
22// Platform-specific implementations
23// packages/web/src/components/LoginForm.tsx
24import { useAuth } from '@myapp/shared';
25import { useNavigate } from 'react-router-dom';
26
27const WebLoginForm = () => {
28 const { login } = useAuth();
29 const navigate = useNavigate();
30
31 const handleSubmit = async (e) => {
32 e.preventDefault();
33 await login(credentials);
34 navigate('/dashboard');
35 };
36
37 return (
38 <form onSubmit={handleSubmit}>
39 {/* Web-specific form */}
40 </form>
41 );
42};
43
44// packages/mobile/src/screens/LoginScreen.tsx
45import { useAuth } from '@myapp/shared';
46import { useNavigation } from '@react-navigation/native';
47
48const MobileLoginScreen = () => {
49 const { login } = useAuth();
50 const navigation = useNavigation();
51
52 const handleSubmit = async () => {
53 await login(credentials);
54 navigation.navigate('Dashboard');
55 };
56
57 return (
58 <View>
59 {/* Native-specific form */}
60 </View>
61 );
62};

Advertisement Space - bottom-comparison

Google AdSense: horizontal

Related Resources

Master Both Platforms

Learn to build amazing experiences on web and mobile with React.

Start Learning →