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

React Native WebView仅首次加载成功,二次加载失败求助

React Native抽屉导航里WebView二次加载失败的解决办法

我在React Native应用里做了个抽屉导航侧边栏,其中一个选项点进去是带WebView的页面加载网站。第一次进完全正常,但退出后再从侧边栏点进去,WebView就彻底加载不出来了。第一次加载时onLoadProgress的nativeEvent日志能正常打出来,之后再进连日志都没有。试了加key属性之类的方法都没用,现在想解决这个问题,让每次从抽屉导航进去都能成功加载WebView。

我的代码是这样的:

const [modalVisible, setModalVisible] = useState(true);

const navChange= (navState: any) => {
   console.log(navState.nativeEvent)
   if (navState.nativeEvent.url.includes('main-page')) {
       setModalVisible(false);
       navigation.navigate('MainPage');
       }
   };

<Modal
       animationType="fade"
       transparent={true}
       visible={modalVisible} 
   >
       <View style={styles.container}>
           <View style={styles.body}>
               <WebView 
                   key={new Date().getTime()} 
                   source={{ uri: 'https://my-website-port/my-website' }} 
                   onLoadProgress={navChange}
                   javaScriptEnabled={true} 
               />
           </View>
       </View>
   </Modal>

问题根源

大概率是这两个原因:

  • Modal切换visible状态时,WebView组件没被正确销毁重建,残留了缓存或内部状态
  • 用new Date().getTime()当key看似每次都变,但Modal的渲染逻辑可能没触发WebView的卸载/重建流程,导致复用了之前的失效实例

解决思路

1. 把WebView做成独立页面(推荐)

别用Modal套WebView了,直接把WebView做成抽屉导航的一个独立屏幕组件。这样每次从抽屉点进去,页面组件都会重新实例化,WebView自然会重新加载,根本不会有残留问题。

代码示例:

// WebViewScreen.js
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { WebView } from 'react-native-webview';

const WebViewScreen = ({ navigation }) => {
  const navChange = (navState) => {
    console.log(navState.nativeEvent);
    if (navState.nativeEvent.url.includes('main-page')) {
      navigation.navigate('MainPage');
    }
  };

  return (
    <View style={styles.container}>
      <WebView
        source={{ uri: 'https://my-website-port/my-website' }}
        onLoadProgress={navChange}
        javaScriptEnabled={true}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

export default WebViewScreen;

然后在抽屉导航里注册这个页面:

import { createDrawerNavigator } from '@react-navigation/drawer';
import WebViewScreen from './WebViewScreen';
import MainPage from './MainPage';

const Drawer = createDrawerNavigator();

function DrawerNavigator() {
  return (
    <Drawer.Navigator>
      <Drawer.Screen name="WebViewPage" component={WebViewScreen} />
      <Drawer.Screen name="MainPage" component={MainPage} />
    </Drawer.Navigator>
  );
}

2. 非要用Modal的话,强制销毁重建WebView

如果业务上必须用Modal承载,那就要确保每次Modal显示时,WebView是完全重新初始化的:

  • 加个独立状态控制WebView的渲染,别只依赖key
  • 显示Modal时延迟渲染WebView,隐藏时立即销毁

代码示例:

import React, { useState, useEffect } from 'react';
import { View, Modal, StyleSheet } from 'react-native';
import { WebView } from 'react-native-webview';

const YourComponent = ({ navigation }) => {
  const [modalVisible, setModalVisible] = useState(false);
  const [shouldRenderWebView, setShouldRenderWebView] = useState(false);

  // Modal显示时延迟渲染WebView,隐藏时立即销毁
  useEffect(() => {
    if (modalVisible) {
      const timer = setTimeout(() => {
        setShouldRenderWebView(true);
      }, 100);
      return () => clearTimeout(timer);
    } else {
      setShouldRenderWebView(false);
    }
  }, [modalVisible]);

  const navChange = (navState) => {
    console.log(navState.nativeEvent);
    if (navState.nativeEvent.url.includes('main-page')) {
      setModalVisible(false);
      navigation.navigate('MainPage');
    }
  };

  // 抽屉点击触发显示Modal
  const handleDrawerItemPress = () => {
    setModalVisible(true);
  };

  return (
    <>
      {/* 这里放你的主界面内容 */}
      <Modal
        animationType="fade"
        transparent={true}
        visible={modalVisible}
        onRequestClose={() => setModalVisible(false)}
      >
        <View style={styles.container}>
          <View style={styles.body}>
            {shouldRenderWebView && (
              <WebView
                source={{ uri: 'https://my-website-port/my-website' }}
                onLoadProgress={navChange}
                javaScriptEnabled={true}
              />
            )}
          </View>
        </View>
      </Modal>
    </>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'rgba(0,0,0,0.5)',
  },
  body: {
    width: '100%',
    height: '100%',
    backgroundColor: 'white',
  },
});

export default YourComponent;

3. 额外措施:清除WebView缓存

要是怀疑是缓存搞的鬼,可以在Modal显示时清一下缓存:

import { WebView } from 'react-native-webview';

useEffect(() => {
  if (modalVisible) {
    WebView.clearCache(true); // true表示同时清cookie
  }
}, [modalVisible]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:38:09