TIL: RN | WebView 통신 - postMessage/onMessage

Lumpen·2023년 3월 7일
1

WebView

목록 보기
4/8

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

web -> mobile

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 -> web

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 라고 함
profile
떠돌이 생활을 하는. 실업자는 아니지만, 부랑 생활을 하는

0개의 댓글