Skip to content

Commit 61161d9

Browse files
committed
Change useWebViewMessage and emit API
1 parent c95c679 commit 61161d9

File tree

10 files changed

+53
-42
lines changed

10 files changed

+53
-42
lines changed

README.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ The communication between React app and React Native app will be also simplified
2525
- All JS modules (with or without JSX/TypeScript) will be bundled with [esbuild](https://github.com/evanw/esbuild).
2626
- **NOTE: Only the edits in the entry file of web will invoke rebuild because of the limitation of [metro](https://github.com/facebook/metro)'s build process.**
2727
- Handle communication between React Native and WebView with React hook style
28-
- With `useWebViewMessage` hook, you can subscribe messages from WebView.
29-
- With `useNativeMessage` hook, you can subscribe messages from React Native.
30-
- `emit` function sends message.
28+
- With `useWebViewMessage` hook, you can subscribe messages from WebView sent with `emitToWebView`.
29+
- With `useNativeMessage` hook, you can subscribe messages from React Native sent with `emitToNative`.
3130
- Support bundling some assets in web side with [ES6 import syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
3231
- `.json` is imported as an object, like require in Node.js.
3332
- `.txt` and `.md` are imported as string, like [raw-loader](https://github.com/webpack-contrib/raw-loader).
@@ -157,7 +156,7 @@ module.exports = (async () => {
157156
import React, { useState } from "react";
158157
import {
159158
webViewRender,
160-
emit,
159+
emitToNative,
161160
useNativeMessage,
162161
} from "react-native-react-bridge/lib/web";
163162
// Importing css is supported
@@ -179,10 +178,10 @@ const Root = () => {
179178
<div>{data}</div>
180179
<button
181180
onClick={() => {
182-
// emit sends message to React Native
181+
// emitToNative sends message to React Native
183182
// type: event name
184183
// data: some data which will be serialized by JSON.stringify
185-
emit({ type: "hello", data: 123 });
184+
emitToNative({ type: "hello", data: 123 });
186185
}}
187186
/>
188187
</div>
@@ -201,18 +200,19 @@ export default webViewRender(<Root />);
201200

202201
import React from "react";
203202
import WebView from "react-native-webview";
204-
import { useWebViewMessage } from "react-native-react-bridge";
203+
import { emitToWebView, useWebViewMessage } from "react-native-react-bridge";
205204
import webApp from "./WebApp";
206205

207206
const App = () => {
207+
const ref = useRef(null);
208208
// useWebViewMessage hook create props for WebView and handle communication
209209
// The argument is callback to receive message from React
210-
const { ref, onMessage, emit } = useWebViewMessage((message) => {
211-
// emit sends message to React
210+
const onMessage = useWebViewMessage((message) => {
211+
// emitToWebView sends message to React
212212
// type: event name
213213
// data: some data which will be serialized by JSON.stringify
214214
if (message.type === "hello" && message.data === 123) {
215-
emit({ type: "success", data: "succeeded!" });
215+
emitToWebView(ref, { type: "success", data: "succeeded!" });
216216
}
217217
});
218218

e2e/index.spec.tsx-snapshots/smoke-webview-with-json-jsx-1-chromium.txt

+5-5
Large diffs are not rendered by default.

examples/DempApp/WebApp/index.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, {useState} from 'react';
22
import {
33
webViewRender,
4-
emit,
4+
emitToNative,
55
useNativeMessage,
66
} from 'react-native-react-bridge/lib/web';
77
import './example.css';
@@ -29,7 +29,7 @@ const Root = () => {
2929
</div>
3030
<textarea value={data} onChange={e => setData(e.target.value)} />
3131
<div>
32-
<Button onClick={() => emit({type: 'hi', data: data})}>
32+
<Button onClick={() => emitToNative({type: 'hi', data: data})}>
3333
send to React Native
3434
</Button>
3535
</div>

examples/DempApp/app/(tabs)/index.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from "react";
1+
import React, { useRef, useState } from "react";
22
import {
33
SafeAreaView,
44
StyleSheet,
@@ -8,12 +8,13 @@ import {
88
TextInput,
99
} from "react-native";
1010
import WebView from "react-native-webview";
11-
import { useWebViewMessage } from "react-native-react-bridge";
11+
import { emitToWebView, useWebViewMessage } from "react-native-react-bridge";
1212
import webApp from "../../WebApp";
1313

1414
const App = () => {
1515
const [data, setData] = useState("This is React Native");
16-
const { ref, onMessage, emit } = useWebViewMessage((message) => {
16+
const ref = useRef<WebView>(null);
17+
const onMessage = useWebViewMessage<string>((message) => {
1718
if (message.type === "hi") {
1819
setData(message.data);
1920
}
@@ -36,7 +37,7 @@ const App = () => {
3637
value={data}
3738
/>
3839
<Pressable
39-
onPress={() => emit({ type: "hello", data: data })}
40+
onPress={() => emitToWebView(ref, { type: "hello", data: data })}
4041
style={styles.button}
4142
>
4243
<Text>send to Web</Text>

src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
* @module
55
*/
66
export type { ReactNativeMessage, WebViewMessage } from "./types";
7-
export { useWebViewMessage } from "./native";
7+
export { useWebViewMessage, emitToWebView } from "./native";

src/native/index.ts

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useRef } from "react";
1+
import { RefObject, useCallback } from "react";
22
import type WebView from "react-native-webview";
33
import type { WebViewMessageEvent, WebViewProps } from "react-native-webview";
44
import { TO_WEB_EVENT_KEY } from "../constants";
@@ -28,23 +28,25 @@ export const buildEmitToWebView = <T>(
2828
export const useWebViewMessage = <T>(
2929
onSubscribe: (message: WebViewMessage<T>) => void
3030
) => {
31-
const ref = useRef<WebView>(null);
32-
const onMessage: WebViewProps["onMessage"] = useCallback(
33-
(event: WebViewMessageEvent) => {
31+
return useCallback(
32+
((event: WebViewMessageEvent) => {
3433
try {
3534
const res = JSON.parse(event.nativeEvent.data);
3635
onSubscribe({ type: res.type, data: res.data });
3736
} catch (e) {
3837
// NOP
3938
}
40-
},
39+
}) satisfies WebViewProps["onMessage"],
4140
[onSubscribe]
4241
);
43-
const emit = useCallback(
44-
(message: ReactNativeMessage<T>) => {
45-
ref.current?.injectJavaScript(buildEmitToWebView(message));
46-
},
47-
[ref]
48-
);
49-
return { ref, onMessage, emit };
42+
};
43+
44+
/**
45+
* A function to send a message to WebView.
46+
*/
47+
export const emitToWebView = <T>(
48+
ref: RefObject<WebView>,
49+
message: ReactNativeMessage<T>
50+
) => {
51+
ref.current?.injectJavaScript(buildEmitToWebView(message));
5052
};

src/web/core.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const getWebViewRootElement = (): HTMLElement =>
88
document.getElementById(WEB_ROOT_ID)!;
99

1010
/**
11-
* A function to send a message to React Native
11+
* A function to send a message to React Native.
1212
*/
1313
export const emitToNative = <T>(message: WebViewMessage<T>) => {
1414
(window as any).ReactNativeWebView.postMessage(JSON.stringify(message));

src/web/preact.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
*/
66
import { useEffect } from "preact/compat";
77
import { render, ComponentChild } from "preact";
8-
import { listenNativeMessage, emitToNative, getWebViewRootElement } from "./core";
8+
import {
9+
listenNativeMessage,
10+
emitToNative,
11+
getWebViewRootElement,
12+
} from "./core";
913
import type { ReactNativeMessage } from "../types";
1014

1115
/**
@@ -28,4 +32,4 @@ export const useNativeMessage = <T>(
2832
useEffect(() => listenNativeMessage(onSubscribe), [onSubscribe]);
2933
};
3034

31-
export { emitToNative as emit };
35+
export { emitToNative };

src/web/react.spec.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @vitest-environment jsdom
22
import { afterEach, describe, expect, it } from "vitest";
33
import { cleanup, render, screen, waitFor } from "@testing-library/react";
4-
import { useNativeMessage, emit } from "./react";
4+
import { useNativeMessage, emitToNative } from "./react";
55
import { useWebViewMessage, buildEmitToWebView } from "../native";
66
import { useEffect, useState } from "react";
77
import { ReactNativeMessage, WebViewMessage } from "../types";
@@ -88,7 +88,7 @@ describe("send message to native", () => {
8888
return (
8989
<button
9090
onClick={() => {
91-
emit(message);
91+
emitToNative(message);
9292
}}
9393
>
9494
send
@@ -98,7 +98,7 @@ describe("send message to native", () => {
9898
const NativeApp = ({ target }: { target: string }) => {
9999
const [data, setData] = useState<null | string>(null);
100100
const [count, setCount] = useState(0);
101-
const { onMessage } = useWebViewMessage<string>((m) => {
101+
const onMessage = useWebViewMessage<string>((m) => {
102102
if (m.type === target) {
103103
setData(m.data);
104104
}

src/web/react.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
import { ReactElement, useEffect } from "react";
77
import { render } from "react-dom";
88
import { createRoot } from "react-dom/client";
9-
import { emitToNative, getWebViewRootElement, listenNativeMessage } from "./core";
9+
import {
10+
emitToNative,
11+
getWebViewRootElement,
12+
listenNativeMessage,
13+
} from "./core";
1014
import type { ReactNativeMessage } from "../types";
1115

1216
/**
@@ -37,4 +41,4 @@ export const useNativeMessage = <T>(
3741
useEffect(() => listenNativeMessage(onSubscribe), [onSubscribe]);
3842
};
3943

40-
export { emitToNative as emit };
44+
export { emitToNative };

0 commit comments

Comments
 (0)