API

nsh/webview

nsh/webview exports WebView: a web page shown by the platform’s own browser engine (WKWebView on iOS and Mac Catalyst, android.webkit.WebView on Android). It is a native view laid out like any other, so it scrolls, clips and overlaps other views correctly.

import { WebView, type WebViewNavigation, type WebViewProps } from "nsh/webview";

See Web view and video for the guide and <WebView> for its props.

#WebView

const WebView: (props: WebViewProps) => YNode;

interface WebViewProps extends Omit<ViewProps, "children" | "ios">, WebViewHostProps {
  source: string | { uri: string } | { html: string; baseUrl?: string };
  ios?: IOSWebViewHostProps;
}
import { mount, signal, Text, View, type YNode } from "nsh";
import { WebView, type WebViewNavigation } from "nsh/webview";

function Browser() {
  const nav = signal<WebViewNavigation | null>(null);
  let web!: YNode;
  return (
    <View style={{ flex: 1 }}>
      <View style={{ flexDirection: "row", gap: 16, padding: 12 }}>
        <Text onPress={() => web.goBack()} style={{ opacity: nav()?.canGoBack ? 1 : 0.4 }}>Back</Text>
        <Text onPress={() => web.reload()}>Reload</Text>
        <Text numberOfLines={1} style={{ flex: 1 }}>{nav()?.title ?? ""}</Text>
      </View>
      <WebView ref={web} source="https://example.com" style={{ flex: 1 }} onNavigationStateChange={(n) => nav.set(n)} />
    </View>
  );
}

mount(Browser);

#Props

WebView takes the view props (style, classes, layout, accessibility, ref; no children), plus:

PropTypeDefaultDescription
sourcestring | { uri: string } | { html: string; baseUrl?: string }(required)A URL, { uri }, or inline HTML with an optional base URL for its relative links.
injectedJavaScriptstringRuns after each page loads.
injectedJavaScriptBeforeContentLoadedstringRuns before each page’s own scripts.
userAgentstringplatform’sThe user agent string.
scrollEnabledbooleantrueThe user can scroll the page.
javaScriptEnabledbooleantruePages run scripts.
ios{ allowsBackForwardNavigationGestures?: boolean }iOS only: swipe from the edges to go back and forward.

#Events

EventPayloadWhen
onLoadStartWebViewNavigationA page starts loading.
onLoadWebViewNavigationA page finished loading.
onError{ message: string }A page failed to load.
onNavigationStateChangeWebViewNavigationThe URL, title, loading state or history changed.
onMessage{ data: string }The page called window.ReactNativeWebView.postMessage(data).
interface WebViewNavigation {
  url: string;
  title: string;
  loading: boolean;
  canGoBack: boolean;
  canGoForward: boolean;
}

#Ref methods

MethodDescription
reload()Reloads the page.
goBack()Goes back in its history.
goForward()Goes forward in its history.
stopLoading()Stops loading.
injectJavaScript(script)Runs script in the page.
postMessage(data)Sends data (a string) to the page: a message event on window, with data as event.data.

#Talking to the page

The page sends strings to the app with window.ReactNativeWebView.postMessage(…); the app sends strings to the page with ref.postMessage(…). Send JSON for structured data.

const page = `<!doctype html><html><head><meta name="viewport" content="width=device-width"></head>
<body>
  <button onclick="window.ReactNativeWebView.postMessage('hello from the page')">Post to the app</button>
  <p id="got"></p>
  <script>
    window.addEventListener('message', (e) => { document.getElementById('got').textContent = e.data; });
  </script>
</body></html>`;

let web!: YNode;
const message = signal("");

<WebView ref={web} source={{ html: page }} style={{ height: 200 }} onMessage={(e) => message.set(e.data)} />
<Text onPress={() => web.postMessage("hi from the app")}>Post to the page</Text>

#Capabilities

When your app declares capabilities in nsh.json, a web view may only show and navigate to the hosts listed under webview; other top-level navigations are refused natively. An app without a capabilities key may show anything. See Sandbox and capabilities.

{
  "capabilities": {
    "webview": { "hosts": ["example.com", "*.example.com"] }
  }
}