MENU
React Native WebView
If your Next.js site is already built, already deployed, and you mainly want an icon in the Apple App Store and Google Play Store rather than a rebuilt native UI, the react-native-webview package is the fastest way to get there. It gives you a <WebView> component -- a native view that embeds a full browser engine (WKWebView on iOS, the system WebView on Android) -- and you point it at your live, deployed Next.js URL. The React Native app itself is just a thin native frame around your existing website.
This is different from a plain PWA install (see Progressive Web App) mainly in distribution: a WebView app is a real binary you submit to the app stores, so it shows up in store search and can be installed the way users expect a "real app" to be installed, even though under the hood it's still rendering your web app's HTML and JavaScript.
Basic usage
At minimum, a WebView-based app is a single screen whose entire body is a <WebView> pointed at a URL. Everything else -- navigation, state, data fetching -- continues to be handled by your Next.js app running inside the WebView, exactly as it would in a mobile browser tab.
terminal:
npx expo install react-native-webviewApp.tsx:
import { SafeAreaView, StyleSheet } from 'react-native'
import { WebView } from 'react-native-webview'
export default function App() {
return (
<SafeAreaView style={styles.container}>
<WebView
source={{ uri: 'https://www.example-nextjs-app.com' }}
style={styles.webview}
pullToRefreshEnabled
startInLoadingState
/>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
container: { flex: 1 },
webview: { flex: 1 },
})For most sites this basic setup already covers navigation -- clicking a link inside the WebView just loads the next page of your Next.js app inside the same WebView, the same way it would in a normal browser tab. If you need to react to navigation from the native side (to update a native tab bar title, for example), the onNavigationStateChange prop reports the current URL.
App.tsx:
import { WebView } from 'react-native-webview'
import { Share } from 'react-native'
<WebView
source={{ uri: 'https://www.example-nextjs-app.com' }}
onMessage={(event) => {
const data = JSON.parse(event.nativeEvent.data)
if (data.type === 'SHARE') {
Share.share({ message: data.url })
}
}}
/>app,share-button.tsx (in the Next.js app):
'use client'
export default function ShareButton({ url }: { url: string }) {
const isInNativeShell = typeof window !== 'undefined' && 'ReactNativeWebView' in window
if (!isInNativeShell) return null // hide when viewed as a normal web page
return (
<button
onClick={() =>
(window as any).ReactNativeWebView.postMessage(
JSON.stringify({ type: 'SHARE', url })
)
}
>
Share
</button>
)
}Tradeoffs vs. a "real" React Native app
| Faster to ship | Little to no UI code to write -- you're reusing your entire existing Next.js app as-is. A working app-store submission can happen in a day. |
| Feels less native | Scrolling physics, transitions, and text rendering come from the web engine, not the platform's native UI toolkit, so it rarely feels indistinguishable from a fully native app to attentive users. |
| No native API access by default | Camera, filesystem, Bluetooth, and similar APIs aren't reachable from inside the WebView's web content. You can bridge specific capabilities across with postMessage / onMessage as shown above, but each one is manual, one-off wiring -- there's no general plugin ecosystem like Capacitor's (see Capacitor). |
| Network-dependent | Because the WebView loads your live, deployed URL, the app is unusable offline unless you separately add caching -- either the PWA service worker described in Progressive Web App (which the WebView's browser engine will still honor), or WebView-level caching via its cacheEnabled prop. |
When this approach makes sense
Reach for react-native-webview when the goal is specifically an app-store presence for a site that already exists and is already deployed, and you don't need deep native API access or native-feeling animations -- a marketing site, a content site, an internal tool, or a first version of a product where "listed in the app stores" matters more than "feels perfectly native." Invest in full React Native instead once native performance, native navigation, or non-trivial native device integration become real product requirements -- at that point the amount of custom bridging code a WebView needs starts to rival the cost of just building native screens.