Shared State in React
This guide integrates the state declared in Shared State in React Native with React within a WebView.
Installation
$ npm add @webview-bridge/react @webview-bridge/web$ pnpm add @webview-bridge/react @webview-bridge/web$ yarn add @webview-bridge/react @webview-bridge/weblinkBridge
Use the linkBridge function to connect with the WebView as shown below.
Assume AppBridge, used as a generic, is declared in React Native with the following structure (refer to Shared State in React Native):
React Native Part
// React Native sample
import { bridge, type Bridge } from "@webview-bridge/react-native";
interface AppBridgeState extends Bridge{
count: number;
increase(): Promise<void>;
};
export const appBridge = bridge<AppBridgeState>(({ get, set }) => ({
count: 0,
async increase() {
set({
count: get().count + 1,
});
},
}));
// It is exported via the package.json type field.
export type AppBridge = typeof appBridge;Web Part
// Web
import { linkBridge } from "@webview-bridge/web";
const bridge = linkBridge<AppBridge>({
throwOnError: true,
onReady: () => {
console.log("bridge is ready");
},
});useBridge
The useBridge hook allows you to access shared state.
With Selector
Insert the previously bridge.store as the first argument and a selector as the second. Using a selector optimizes rendering.
For example, the code below only re-renders when the count value changes.
import { useBridge } from "@webview-bridge/react";
function Count() {
// render when only count changed
const count = useBridge(bridge.store, (state) => state.count);
return <p>Native Count: {count}</p>;
}Without Selector
Retrieve without a selector. However, it re-renders if any value changes.
import { useBridge } from "@webview-bridge/react";
function CountAndIncrease() {
// render when any value changes
const { count, increase } = useBridge(bridge.store);
return (
<div>
<p>Native Count: {count}</p>
<button onClick={() => increase()}>Increase</button>
</div>
);
}With a Provider
createLinkBridgeProvider creates the bridge together with a BridgeProvider and hooks bound to it. It takes the same options as linkBridge, and it is the recommended setup for SSR frameworks.
import { createLinkBridgeProvider } from "@webview-bridge/react";
import type { AppBridge, AppPostMessageSchema } from ""; // types exported from React Native
export const {
BridgeProvider,
useBridgeStore, // shared state and native methods, with a selector
useBridgeStatus, // { isWebViewBridgeAvailable, isNativeMethodAvailable }
useBridgeLoose, // { loose }
useBridgeEventListener, // listen to postMessage events
} = createLinkBridgeProvider<AppBridge, AppPostMessageSchema>({
throwOnError: true,
});
function Count() {
const count = useBridgeStore((state) => state.count);
const { isWebViewBridgeAvailable } = useBridgeStatus();
useBridgeEventListener("eventName1", (message) => {
console.log(message);
});
return <p>Native Count: {isWebViewBridgeAvailable ? count : "-"}</p>;
}Render the components inside <BridgeProvider>. If native announces its methods after the first render (which can happen on Android), useBridgeStore and useBridgeStatus re-render with them.
See Next.js (App Router) and Remix for complete setups.
NOTE
You can explore a practical example and further understand the implementation by visiting bellow.