Introduction
React Native has a quote: "write once, run everywhere." But honestly, I always felt like something was missing. Sure, we could target iOS and Android, but what about the web? That's where millions of users spend their time every day. Then I stumbled upon React Native for Web, and let me tell you – it was a game-changer. Suddenly, that same codebase I'd been pouring my heart into for mobile apps could reach web users too. If you already have a react-native app then you can convert your app code easily to web with minimal changes.
What Exactly is React Native for Web?
Think of React Native for Web as your friendly translator. It takes all those React Native components you know and love – View
, Text
, Image
– and magically transforms them into their web equivalents. Your View
becomes a div
, your Text
becomes a span
or p
element. Specifically, the span
element is used for text that is part of a larger text flow (inline), while the p
element is used for standalone paragraphs. , and your Image
becomes an img
tag. It's like having a universal language for UI development.
The best part? If you're already using Expo, web support is baked right in.
Advantages of using React-Native for web:
Look, I've been around the block. I've built separate React apps for web and React Native apps for mobile. I've felt the pain of duplicating logic, styling components twice, and keeping everything in sync. Here's why React Native for Web changed everything for me:
- Zero Configuration Stress: Expo handles all the heavy lifting. I can focus on building features instead of fighting build tools.
- My Code Gets Reused: Not just the business logic – the entire UI components work across platforms. That custom button I spent hours perfecting? It looks and works the same everywhere.
- SEO That Actually Works: With App Router, I get proper URLs and SEO-friendly routing.
- Time is Money: Instead of juggling multiple codebases, I can ship features faster as the codebase is shared.
Getting Started
First, let's create our project. To create the project, I am using Expo. Here are the commands to create the basic boilerplate using Expo:
npx create-expo-app my-app
cd my-app
Now, fire up the development server:
npx expo start
Press w
in your terminal, and watch your React Native app open in your browser.
Explore App Router
Expo’s App Router is like Next.js for React Native – filesystem-based routing that works out of the box. Just create folders and files, and Expo handles the routes automatically.
- In the
app/
directory (this already exists in new Expo projects):
app/
├── index.tsx // maps to ‘/’
├── about/
│ ├── index.tsx // maps to ‘/about’
│ └── _layout.tsx // optional shared layout for /about pages
- Let’s create our home page:
// app/index.tsx
import { View, Text, Pressable } from 'react-native';
import { Link } from 'expo-router';
export default function Home() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 24 }}>Welcome to React Native Web with Expo!</Text>
<Link href="/about">
<Pressable>
<Text style={{ color: 'blue', marginTop: 20 }}>Go to About Page</Text>
</Pressable>
</Link>
</View>
);
}
- About page:
// app/about/index.tsx
import { View, Text, Pressable } from 'react-native';
import { Link } from 'expo-router';
export default function About() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 24 }}>This is the About Page</Text>
<Link href="/">
<Pressable>
<Text style={{ color: 'blue', marginTop: 20 }}>Back to Home</Text>
</Pressable>
</Link>
</View>
);
}
✅ (Optional) Add _layout.tsx for nested layouts if you want shared headers, footers, or other UI elements across pages.
✅ Run your project on web:
npx expo start
Press w
to open in your browser. Navigate to /about and watch the webapp to render.
Handling Flatlist
FlatList on web can be tricky, but when you get it right, it's amazing:
import React from 'react';
import { FlatList, Text, View } from 'react-native';
const DATA = [
{ id: '1', title: 'First item' },
{ id: '2', title: 'Second item' },
{ id: '3', title: 'Third item' },
];
export default function MyList() {
const renderItem = ({ item }) => (
<View style={{
padding: 10,
borderBottomWidth: 1,
borderColor: '#ccc'
}}>
<Text>{item.title}</Text>
</View>
);
return (
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
);
}
Handling API Calls
For any real world webapp we need to handle API calls. To handle API calls in react-native and render elements in UI:
import React, { useEffect, useState } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
export default function DataFetcher() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => {
setData(json);
setLoading(false);
})
.catch(error => {
console.error('Something went wrong! Error: ', error);
setLoading(false);
});
}, []);
if (loading) {
return <ActivityIndicator size="large" color="#0000ff" />;
}
return (
<View>
{data.slice(0, 5).map(item => (
<Text key={item.id}>{item.title}</Text>
))}
</View>
);
}
Handling Responsive Design
Here's how we can handle responsive design for web for different device width:
import { View, Text, useWindowDimensions } from 'react-native';
export default function ResponsiveComponent() {
const { width } = useWindowDimensions();
// to check the device screen is desktop or mobile
const isDesktop = width > 600;
return (
<View style={{
backgroundColor: isDesktop ? 'lightblue' : 'lightgrey',
padding: 20,
}}>
<Text style={{
fontSize: isDesktop ? 24 : 16,
textAlign: isDesktop ? 'left' : 'center'
}}>
This text adapts to your screen size
</Text>
</View>
);
}
Handling code specific for web:
To handle the code specific for web, we can use the Platform API from React Native. From the OS, we can do a check if it's a web browser or not. Here is an example code:
import { Platform, View, Text } from 'react-native';
export default function RenderOnWeb() {
if (Platform.OS === 'web') {
return (
<View style={{ padding: 20, backgroundColor: '#f0f0f0' }}>
<Text style={{ fontSize: 18 }}>This is rendered only on Web</Text>
</View>
);
}
// Optionally render something else for mobile
return (
<View style={{ padding: 20, backgroundColor: '#e0ffe0' }}>
<Text style={{ fontSize: 18 }}>This is rendered on Mobile 📱</Text>
</View>
);
}
Conclusion
React Native for Web helps us to convert our existing mobile app code to web without creating a new project. It's about building once and deploying everywhere, without sacrificing quality or performance. At the end of the day no library or framework is good or bad. It's all about the use case and tradeoffs. Start with something simple – maybe just a landing page or a basic dashboard, and then move in to some more complex apps. If you like this blog and want to learn more about Frontend Development and Software Engineering, you can follow me on Dev.to.
Top comments (0)