FrontEnd/React & React-Native

[React-Native] React-Native-Webview(์›น๋ทฐ) ๋ฐ์ดํ„ฐ ํ†ต์‹  Feat. PostMessage

devwoodie 2024. 2. 23. 11:34
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ“œ Webview PostMessage


ํšŒ์‚ฌ์—์„œ ์•ฑ์„ ๊ฐœ๋ฐœํ•  ๋•Œ React-Native webview๋กœ React ํ”„๋กœ์ ํŠธ๋ฅผ ์”Œ์›Œ์„œ ์•ฑ ๋“ฑ๋ก์„ ํ•˜์˜€๋‹ค.
๊ทธ๋•Œ RN -> React ๋˜๋Š” React -> RN ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์•ผํ•˜๋Š” ์ผ์ด ์ƒ๊ธด๋‹ค.
(์•ฑ์„ ์ผฐ์„ ๋•Œ osํ™•์ธ์„ ํ•˜๊ฑฐ๋‚˜, ์ ‘์† ์œ„์น˜๋ฅผ ํ™•์ธํ•ด react์—์„œ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋“ฑ)


๊ทธ ๋‹น์‹œ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ๋ฒ•์„ ๊ธฐ๋กํ•ด ๋†“์œผ๋ ค๊ณ  ํ•œ๋‹ค.

๐Ÿ” React-Native Webview ์˜ต์…˜ ์„ธํŒ…

React-Native webview ์ž‘์—… ์‹œ onMessage ์†์„ฑ์— react์—์„œ ๋ณด๋‚ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•  ํ•จ์ˆ˜๋ฅผ ์ ๋Š”๋‹ค.

const webview = useRef();
<WebView
    style={{backgroundColor: "#000"}}
    overScrollMode="never"
    ref={webview}
    mixedContentMode={'always'}
    mediaPlaybackRequiresUserAction={false}
    javaScriptEnabled={true}
    domStorageEnabled={true}
    startInLoadingState={true}
    originWhitelist={['*']}
    allowsInlineMediaPlayback={true}
    injectedJavaScript={debugging}
    onNavigationStateChange={onNavigationStateChange}
    // onMessage setting
    onMessage={(e) => {
        web_to_native(e)
    }}
    source={{
        uri: uri,
    }}
/>

๐Ÿ” React-Native -> React

React-Native(๋ณด๋‚ด๊ธฐ)

// type, data ์ „์†ก (react์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ type์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•จ)
await webview.current.postMessage(JSON.stringify({
    type: 'type',
    data:{
        key1: "postData1",
        key2: "postData2"
    }
}));

React(๋ฐ›๊ธฐ)

const listenerData = () => {
    const {key1, key2} = data;
}

const receiveMessage = (event) => {
    // ๋ฐ›์€ ๋ฐ์ดํ„ฐ(type, data)
    const {type, data} = JSON.parse(event.data);

    if(type ==='type'){
        // ๋งŒ๋“ค์–ด ๋†“์€ ํ•จ์ˆ˜์— data ์ „์†ก
        listenerData(data)
    }
}

useEffect(() => {
    // ios
    window.addEventListener('message', receiveMessage);
    // aos
    document.addEventListener('message', receiveMessage);

    return() => {
        // ios
        window.removeEventListener('message', receiveMessage);
        // aos
        document.removeEventListener('message', receiveMessage);
    }
}, []);

๐Ÿ” React -> React-Native

React(๋ณด๋‚ด๊ธฐ)

export const postNativeMessage = async(message, callback) => {
    return new Promise((resolve, reject) => {
        if (window.ReactNativeWebView) {
            const listener = async(event) => {
                // setIsChecked(data)

                clearTimeout(timer);
                /** android */
                document.removeEventListener('message', listener);
                /** ios */
                window.removeEventListener('message', listener);
                resolve(JSON.parse(event.data).result);
            };

            window.ReactNativeWebView.postMessage(message);
            const TIMEOUT = 10000;
            const timer = setTimeout(() => {
                /** android */
                document.removeEventListener('message', listener);
                /** ios */
                window.removeEventListener('message', listener);
                reject('TIMEOUT');
            }, TIMEOUT);

            if(callback){
                /** android */
                document.addEventListener('message', listener);
                /** ios */
                window.addEventListener('message', listener);
            }else {
                clearTimeout(timer);
                return
            }
        } else {
            return
        }
    })
}

// ์‚ฌ์šฉ
await postNativeMessage(JSON.stringify({type: "type1", data: ''}), true);

React-Native(๋ฐ›๊ธฐ)

const web_to_native = async (e) => {
    const {type, data} = JSON.parse(e.nativeEvent.data);

    if (type === "type1") {
        // ์‹คํ–‰ ๋กœ์ง
        console.log(data);
    }
}
728x90
๋ฐ˜์‘ํ˜•