patterntypescriptreact-nativeModerate
React Native Web: Sharing Code Between Mobile and Web
Viewed 0 times
react-native-webwebuniversal appcross-platformPlatform.OS webexpo webSSR
Problem
Maintaining separate React Native and React Web codebases for the same product doubles development effort. Sharing components requires careful attention to what APIs are available on web.
Solution
Use
react-native-web (included in Expo). Configure webpack/Metro to resolve RN imports to their web equivalents. Use Platform.OS === 'web' for web-specific code. Avoid APIs unavailable on web (native modules, Linking with custom schemes). Use expo-router which supports web routing out of the box.Why
React Native Web reimplements React Native's component API in CSS/HTML. StyleSheet, View, Text, Pressable, and many others map directly to DOM elements. This allows 60-80% code sharing between mobile and web without duplication.
Gotchas
- Not all React Native components have web equivalents — check rnw.netlify.app for compatibility
- StyleSheet on web is more permissive than on native — values that fail silently on native can look different on web
- Native modules never work on web — always guard with Platform.OS checks
- expo-router uses Expo's Metro config; custom webpack setups need manual react-native-web aliasing
Code Snippets
Universal Pressable component with web-specific cursor style
import { Platform, Pressable, StyleSheet, Text } from 'react-native';
export function UniversalButton({ onPress, label }: Props) {
return (
<Pressable
onPress={onPress}
style={({ pressed }) => [
styles.button,
Platform.OS === 'web' && styles.webCursor,
pressed && styles.pressed,
]}
>
<Text style={styles.label}>{label}</Text>
</Pressable>
);
}
const styles = StyleSheet.create({
button: { padding: 16, borderRadius: 8, backgroundColor: '#007AFF' },
webCursor: { cursor: 'pointer' } as any, // web-only style
pressed: { opacity: 0.7 },
label: { color: '#fff', fontWeight: '600' },
});Revisions (0)
No revisions yet.