You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native WebView中injectJavascript调用函数失败问题求助

解决React Native WebView中调用window.login提示未定义的问题

环境信息

  • 设备:Apple Macbook Pro 2017 - 13英寸
  • 系统:Macos 13.4.1
  • Xcode:14.3.1

核心依赖版本

{
  "dependencies": {
    "react-native": "0.71.8",
    "react-native-webview": "11.26.0"
  }
}

错误提示

WARN Error evaluating injectedJavaScript: This is possibly due to an unsupported return type. Try adding true to the end of your injectedJavaScript string. Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=1, WKJavaScriptExceptionMessage=TypeError: window.login is not a function. (In 'window.login("John Smith", "John.Smith.1234", "*****")', 'window.login' is undefined), WKJavaScriptExceptionColumnNumber=13, WKJavaScriptExceptionSourceURL=about:blank, NSLocalizedDescription=A JavaScript exception occurred}

相关代码

WebView组件实现

// ...
static webViewReference = null;
static injectScriptCallback = null;

static injectScript(script) {
  if (GunWebView.webViewReference) {
    GunWebView.webViewReference.injectJavaScript(script);
  } else {
    GunWebView.injectScriptCallback = () => {
      GunWebView.webViewReference.injectJavaScript(script);
    };
  }
}

constructor(props) {
  super(props);
}

render() {
  return (
    <WebView
      onMessage={this.props.onMessage}
      style={this.styles.webView}
      ref={(ref) => {
        GunWebView.webViewReference = ref;
      }}
      originWhitelist={["*"]}
      javaScriptEnabled={true}
      javaScriptEnabledAndroid={true}
      source={{ html: GUN_WEB_ABSTRACTION }}
      onLoadEnd={() => {
        if (GunWebView.injectScriptCallback) {
          GunWebView.injectScriptCallback();
          GunWebView.injectScriptCallback = null;
        }
      }}
    />
  );
}
// ...

GUN_WEB_ABSTRACTION 页面代码

<script>
  // --END OF LIBRARY IMPORT--

  (function (){
  window.gun = new Gun("******************"); // Custom relay server (Unable to show)
  
  // Authentication functions:
  window.login = function (username, password, pid) {
    window.gun.user().auth(username, password, (ack) => {
      window.ReactNativeWebView.postMessage(JSON.stringify({pid ...ack}));
    });
  }
  
  window.loginWithKeyPair = function (kayPair, pid) {
    window.gun.user().auth(keyPair, (ack) => {
      window.ReactNativeWebView.postMessage(JSON.stringify({pid ...ack}));
    });
  }})();
</script>
<!-- --END OF GUN HTML-- -->

调用逻辑

function injectJavascript(script: string) {
  GunWebView.injectScript(script);
}

// ...

export function login(username: string, password: string) {
  // ...
  return new Promise((resolve, reject) => {
    const PID = uuid.v4();

    registerProcess(PID, (ack: any) => {
      if (ack.err) {
        reject(ack.err);
      } else {
        resolve(ack);
      }
    });

    injectJavascript(`window.login("${username}", "${password}", "${PID}");`);
     
    // ... Error handling and etc ...
  });
}

解决方案

1. 修复脚本语法错误

GUN页面代码存在两处语法错误,会导致脚本执行失败,window.login无法挂载:

  • 对象展开语法错误:{pid ...ack} → {pid, ...ack}
  • 参数名拼写错误:kayPair → keyPair

修正后的脚本:

<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script>
  (function (){
  window.gun = new Gun("******************"); // Custom relay server
  
  // Authentication functions:
  window.login = function (username, password, pid) {
    window.gun.user().auth(username, password, (ack) => {
      window.ReactNativeWebView.postMessage(JSON.stringify({pid, ...ack}));
    });
  }
  
  window.loginWithKeyPair = function (keyPair, pid) {
    window.gun.user().auth(keyPair, (ack) => {
      window.ReactNativeWebView.postMessage(JSON.stringify({pid, ...ack}));
    });
  }})();

  // 通知RN脚本初始化完成
  window.ReactNativeWebView.postMessage(JSON.stringify({type: 'GUN_INIT_SUCCESS'}));
</script>

2. 确保GUN库已正确加载

原代码缺少GUN.js的引入,必须在初始化window.gun前加载GUN库,可使用CDN或本地打包的脚本文件。

3. 替换WebView加载完成逻辑

onLoadEnd触发时页面脚本可能还未完全执行,改为监听WebView发送的初始化完成消息再执行注入:

render() {
  return (
    <WebView
      onMessage={(event) => {
        const messageData = JSON.parse(event.nativeEvent.data);
        // 处理GUN初始化完成的消息
        if (messageData.type === 'GUN_INIT_SUCCESS') {
          if (GunWebView.injectScriptCallback) {
            GunWebView.injectScriptCallback();
            GunWebView.injectScriptCallback = null;
          }
        } else {
          // 转发其他消息给父组件
          this.props.onMessage(event);
        }
      }}
      style={this.styles.webView}
      ref={(ref) => {
        GunWebView.webViewReference = ref;
      }}
      originWhitelist={["*"]}
      javaScriptEnabled={true}
      javaScriptEnabledAndroid={true}
      domStorageEnabled={true} // 开启DOM存储,GUN依赖此特性
      source={{ html: GUN_WEB_ABSTRACTION }}
    />
  );
}

4. 修复injectJavaScript返回值问题

按照错误提示,在注入脚本末尾添加;true,确保返回支持的布尔类型:

injectJavascript(`window.login("${username}", "${password}", "${PID}");true;`);

5. 避免字符串插值的安全问题

如果用户名/密码包含引号,直接字符串插值会导致语法错误,建议用JSON.stringify处理参数:

const script = `window.login(${JSON.stringify(username)}, ${JSON.stringify(password)}, ${JSON.stringify(PID)});true;`;
injectJavascript(script);

内容的提问来源于stack exchange,提问作者Alvin Cheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:25:25