React Native WebView 를 통해
React Native와 WebView 에서 사용하는 웹의
통신을 구현할 수 있다
WebView 를 통해 접근한 웹의 window 객체 내에 ReactNativeWebView 라는 속성이 추가된다
React Native WebView 태그에서
injectedJavascript, onMessage 속성을 통해 구현할 수 있다
https://stackoverflow.com/questions/68334181/how-to-use-postmessage-in-a-react-native-webview
const WebViewComponent = () => {
const INJECTED_JAVASCRIPT = `(function() {
window.ReactNativeWebView.postMessage(JSON.stringify({key : "value"}));
})();`;
const onMessage = (event) => {
const data = JSON.parse(event.nativeEvent.data);
Alert.alert(data.key);
}
return (
<WebView source={{ uri: "uri" }}
onMessage={onMessage}
injectedJavaScript={INJECTED_JAVASCRIPT}
/>
)
}
주의할점
WebView 통신은 string 만 가능하다
web 을 react 로 구성했다면 injectedJavaScript 에서 찾을 수 있는 것은
react의 index 에서 사용중인 root (내 경우에는 <div id="root" />
)
뿐인 것 같다..
-> WebView 로 웹을 띄울 때 csr 이기 때문에 빈 div 만 오는것..
-> web 코드에서 postMessage() 를 작성해야 한다
web 코드에 postMessage() 추가
JSON.stringyfy({key: boolean})
의 경우 숫자 값으로 변환되니 주의해야 한다
JSON.stringyfy({key: String(boolean)})
으로 전송하여 해결..
useLayoutEffect(() => {
// @ts-ignore
const { ReactNativeWebView } = window; // web 으로 접속 시 null, WebView로 접속 시에만 있음
if (ReactNativeWebView)
ReactNativeWebView.postMessage(
JSON.stringify({ key: JSON.stringify(state) })
);
}, [state])
mobile
import React, {useRef. useEffect} from 'react'
import WebView from 'react-native-webview';
const WebViewComponent = () => {
const webViewRef = useRef<WebView>(null);
useEffect(()=>{
webViewRef.current.postMessage('hi')
},[])
return (
<WebView source={{ uri: "uri" }}
ref={webViewRef}
/>
)
}
web
const onMessageEvent = (e: MessageEvent) => {
e.stopPropagation();
setData(String(e.data));
};
React.useEffect(() => {
window.addEventListener("message", onMessageEvent, { capture: true });
return () => window.removeEventListener("message", onMessageEvent);
}, []);
웹에서 메시지를 받기 위해서는
addEventListener('message', callback);
을 사용한다
온라인에 안드로이드의 경우 아래와 같이 작성하라는 글이 많은데
document.addEventListener('message',(e) => alert(e.data) )
아무리 해봐도 document 에 MessageEvent 가 없다..
window.addEventListener("message", onMessageEvent, true);
로 작성하여 ios 와 android 모두 해결
하지만 안드로이드의 경우 message 가 string 이 아닌
object 타입으로 오기 떄문에
event.data 를 string 으로 변환 후 사용할 수 있었다
web -> mobile message 통신에서 iOS 의 경우 시간이 지나면 alert 이 뜬다..
alert() 을 의도적으로 사용중인 부분이 없는데... webpackHotUpdate 라고 함