反応ネイティブ Webview RN と HTML の双方向通信

rnログイン後に取得したトークンをWebページに渡し、jsで取得したブラウザ情報をrnに渡す必要があります

RN インデックス.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,
  }
}

WebpageIndex.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>
  )
}

 

 

 

参考リンク:

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

https://chat.xutongbao.top/ 

おすすめ

転載: blog.csdn.net/xutongbao/article/details/132297521