react-native-webview RN and html two-way communication

rnThe token obtained after logging in needs to be passed to the web page, and the browser information obtained by js needs to be passed to rn

RN Index.js:

import React from 'react'
import { WebView } from 'react-native-webview'
import useList from './useList'

export default function Index(props) {
  const { uri, jsCode, webViewRef, handleMessage, handleLoad } = useList(props)

  return (
    <>
      <WebView
        ref={webViewRef}
        source={
   
   {
          uri,
        }}
        style={
   
   { flex: 1 }}
        injectedJavaScriptBeforeContentLoaded={jsCode} //injectedJavaScriptBeforeContentLoaded injectedJavaScript
        originWhitelist={['*']}
        onMessage={(value) => handleMessage(value)}
        onLoad={() => handleLoad()}
      />
    </>
  )
}

RN useList.js:

import { useState, useEffect, useRef } from 'react'
import AsyncStorage from '@react-native-async-storage/async-storage'
import Constants from 'expo-constants'

export default function useList() {
  let uri =
    Constants.manifest.extra.REACT_APP_MODE === 'dev'
      ? `${Constants.manifest.extra.devHost}:3000/#/single/demo/test1`
      : 'https://chat.xutongbao.top/#/ai/chat'
  const webViewRef = useRef(null)

  const jsCode = `
  window.reactNative = {};
  window.reactNative.testData = 'inject data:1';
  true; // note: this is required, or you'll sometimes get silent failures
`

  const handleLoad = async () => {
    console.log('load')
  }

  const handleMessage = (value) => {
    let payload = value.nativeEvent?.data
      ? JSON.parse(value.nativeEvent.data)
      : {}
    let type = payload.type
    if (type === 'getToken') {
      let fun = async () => {
        const token = await AsyncStorage.getItem('token')

        webViewRef.current.postMessage(
          JSON.stringify({
            type,
            token: token,
          })
        )
      }
      fun()
      webViewRef.current.postMessage(
        JSON.stringify({
          type: 'getBrowserInfo',
        })
      )
    } else if (type === 'getBrowserInfo') {
      console.log(payload)
    }
  }

  useEffect(() => {
    // eslint-disable-next-line
  }, [])

  return {
    uri,
    jsCode,
    webViewRef,
    handleMessage,
    handleLoad,
  }
}

Webpage Index.js:

import React, { useState, useEffect } from 'react'
import uaParser from 'ua-parser-js'
import './index.css'


export default function Index() {
  const [testData, setTestData] = useState()
  const [token, setToken] = useState()

  const handleGetDataFromInjected = () => {
    if (window.reactNative?.testData) {
      setTestData(window.reactNative?.testData)
      setToken(window.reactNative?.token)
    }
  }

  const handleGetToken = () => {
    window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'getToken' }))
  }

  const handleMessage = () => {
    window.document.addEventListener('message', function (e) {
      let payload = e.data ? JSON.parse(e.data) : {}
      let type = payload.type

      if (type === 'getToken') {
        setToken(payload.token)
      } else if (type === 'getBrowserInfo') {
        let ua = uaParser(navigator.userAgent)
        const { browser } = ua
        window.ReactNativeWebView.postMessage(JSON.stringify({ type, browser }))
      }
    })
  }

  useEffect(() => {
    handleGetDataFromInjected()
  }, [])

  useEffect(() => {
    handleGetToken()
  }, [])

  useEffect(() => {
    handleMessage()
  }, [])

  return (
    <div className='m-test1'>
      <div>{testData}</div>
      <div>token:{token}</div>
    </div>
  )
}

 

 

 

Reference links:

https://github.com/react-native-webview/react-native-webview/blob/eb2ce07e728352abe8b11d10a9de2a4fdc2f228b/docs/Guide.md#communicating-between-js-and-native

https://chat.xutongbao.top/ 

Guess you like

Origin blog.csdn.net/xutongbao/article/details/132297521