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

React Native WebView调用网页cancel函数无响应问题求助

React Native WebView 点击返回键无法触发网页端cancel函数的问题

我用React Native WebView加载了一个单页网页,网页执行搜索后会展示结果,重新搜索需要点击设备返回键回到搜索框。因为是单页应用,没法用goBack(),所以在网页端定义了cancel()函数用来清除搜索结果并回到搜索窗口,但现在点击设备返回键时,网页的cancel()函数根本没执行。

我的代码如下:

import React, { useRef, useEffect, useState } from 'react';
import { KeyboardAvoidingView, StatusBar, BackHandler } from 'react-native';
import { WebView } from 'react-native-webview';

export default function App() {
  const webviewRef = useRef(null);
  const [backTapping, setBackTapping] = useState(0);
  
  const backAction = () => {
    setBackTapping((prev) => prev += 1);
    webviewRef.current.injectJavaScript('window.cancel()')
    return true;
  }

  useEffect(() => {
    const timer = setInterval(() => {
      setBackTapping(0)
    }, 1000)
    return () => clearInterval(timer);
  }, [])

  useEffect(() => {
    const backHandler = BackHandler.addEventListener('hardwareBackPress',backAction);
    return () => backHandler.remove()
  }, [])

  useEffect(() => {
    if(backTapping >= 2){
      BackHandler.exitApp();
    }
  },[backTapping])
  

  return (
    <KeyboardAvoidingView style={{ flex: 1 }}>
    <StatusBar hidden />
    
    <WebView
      ref={webviewRef}
      textZoom={100}
      originWhitelist={['*']}
      javaScriptEnabled={true}
      source={{ uri: 'myhome.com'}}
      startInLoadingState={true}
    />
    </KeyboardAvoidingView>
  );
}

预期行为:点击返回键时执行cancel()函数,关闭结果窗口回到搜索窗口。


解决建议

1. 确保window.cancel全局可访问

网页端的cancel函数必须挂载到window对象上,且在WebView加载完成后可用。检查网页代码:

// 网页端代码示例
window.cancel = function() {
  // 清除搜索结果、返回搜索框的逻辑
  console.log('cancel函数执行');
};

如果函数是在模块内部定义的,必须显式暴露到全局作用域,否则WebView无法通过window.cancel调用。

2. 用evaluateJavaScript替代injectJavaScript

injectJavaScript在新版react-native-webview中已被标记为过时,推荐使用evaluateJavaScript,它支持Promise,可捕获执行错误:
修改backAction函数:

const backAction = async () => {
  setBackTapping((prev) => prev + 1);
  try {
    if (webviewRef.current) {
      const result = await webviewRef.current.evaluateJavaScript('window.cancel()');
      console.log('cancel函数执行结果:', result);
    }
  } catch (error) {
    console.error('执行cancel函数出错:', error);
  }
  return true;
};

3. 等待网页完全加载后再执行函数

如果网页未加载完成就调用window.cancel,会因函数不存在而失败。通过onLoadEnd标记加载状态:

const [webLoaded, setWebLoaded] = useState(false);

// ...

<WebView
  ref={webviewRef}
  textZoom={100}
  originWhitelist={['*']}
  javaScriptEnabled={true}
  source={{ uri: 'myhome.com'}}
  startInLoadingState={true}
  onLoadEnd={() => setWebLoaded(true)}
/>

然后在backAction中判断:

const backAction = async () => {
  setBackTapping((prev) => prev + 1);
  if (!webLoaded) return true;
  
  try {
    await webviewRef.current.evaluateJavaScript('window.cancel()');
  } catch (error) {
    console.error('执行失败:', error);
  }
  return true;
};

4. 优化返回键重复触发逻辑

当前定时器逻辑可能导致不必要的循环,调整为点击后才启动定时器:

useEffect(() => {
  let timer;
  if (backTapping > 0) {
    timer = setTimeout(() => {
      setBackTapping(0);
    }, 1000);
  }
  return () => clearTimeout(timer);
}, [backTapping]);

5. 检查网页CSP和WebView配置

确保WebView的javaScriptEnabled显式设为true,同时如果网页有内容安全策略(CSP),需允许执行内联脚本,否则注入的JS代码会被阻止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 04:55:23