Skip to content

Instantly share code, notes, and snippets.

@earthflower
Created January 23, 2023 21:58
Show Gist options
  • Save earthflower/43630023957f8e2b9038df7bfac0a1ba to your computer and use it in GitHub Desktop.
Save earthflower/43630023957f8e2b9038df7bfac0a1ba to your computer and use it in GitHub Desktop.
import React, { useRef, useContext } from 'react';
import { WebView } from 'react-native-webview';
import { Subject, BehaviorSubject } from 'rxjs';
import { map, tap, filter } from 'rxjs/operators';
const WebViewContext = React.createContext();
function WebViewWrapper() {
const webViewRef = useRef(null);
const message$ = new Subject();
const result$ = new BehaviorSubject(null);
const handleMessage = (event) => {
message$.next(event.nativeEvent.data);
};
return (
<WebViewContext.Provider value={{ message$, result$ }}>
<WebView
ref={webViewRef}
onMessage={handleMessage}
source={{ uri: 'https://example.com' }}
/>
</WebViewContext.Provider>
);
}
function MyComponent() {
const { message$, result$ } = useContext(WebViewContext);
message$.pipe(
filter((message) => message.type === 'result'),
map((message) => message.data),
tap((data) => result$.next(data))
).subscribe();
const add = (a, b) => {
webViewRef.current.postMessage("add", [a, b]);
}
const multiply = (a, b) => {
webViewRef.current.postMessage("multiply", [a, b]);
}
return (
<div>
<button onClick={() => add(1, 2)}>Add 1 and 2</button>
<button onClick={() => multiply(3, 4)}>Multiply 3 and 4</button>
<div>{result$.value}</div>
</div>
);
}
@earthflower
Copy link
Author

In this example, we use the useRef hook to create a reference to the WebView component. We also create two Subject from RxJS, one message$ which we use to emit messages when the onMessage event is triggered and one result$ which we use to store the result from the webview. Both subjects are wrapped in a context provider, so that they can be accessed from other components.

In MyComponent, we use the useContext hook to get the message$ and result$ subjects, and then we use the pipe method to filter the messages by type, map the result message data and tap to update the result$.next(data) and subscribe to the observable.

We also have a function add(a, b) which triggers the webViewRef.current.postMessage("add", [a, b]) when clicked. In the JS that runs inside the WebView, you can add a listener for the add message, perform the addition and post back the result as a message with type 'result' to the React Native app.

@earthflower
Copy link
Author

window.addEventListener('message', (event) => {
  const { data } = event;
  const { type, args } = data;
  if(type === 'add') {
    const result = args.reduce((acc, val) => acc + val);
    window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'result', data: result }));
  } else if (type === 'multiply') {
    const result = args.reduce((acc, val) => acc * val);
    window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'result', data: result }));
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment