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

React Native登录页WebViewModal报错:null is not an object

问题

我开发的React Native登录页面遇到一个问题:点击「忘记密码」按钮时,本该弹出包含指定网站的Modal,但现在触发「null is not an object」错误。之前代码运行完全正常,移除WebViewModal组件后Modal能正常显示,推测问题出在WebViewModal组件上,求技术帮助。

排查与解决方案

问题根源分析

  1. Provider作用域错误:WebViewModalProvider被嵌套在Modalize内部,导致WebViewModal无法正确获取上下文,引发空引用错误。
  2. 硬编码visible属性:WebViewModal的visible被设为true,组件初始化时就尝试渲染,而此时Modalize尚未打开,导致WebView相关实例未正确初始化。
  3. 冗余布局组件:Modalize内部嵌套的SafeAreaView可能干扰WebView的布局渲染。

修复步骤

  • 把WebViewModalProvider提升到组件最外层,确保所有子组件能访问到上下文。
  • 使用状态webViewVisible控制WebViewModal的显示,打开Modalize时同步设置该状态为true,关闭时重置为false。
  • 移除Modalize内部多余的SafeAreaView,简化布局结构。

修改后的完整代码

import * as React from 'react';
import { useState, useRef } from 'react';
import {
  Text, StyleSheet,
  KeyboardAvoidingView, ScrollView, Image,
  TextInput, TouchableOpacity, View, SafeAreaView,
} from 'react-native';
import { CheckBox } from 'react-native-elements';
import { Ionicons } from 'react-native-vector-icons'
import { useNavigation } from '@react-navigation/native';
import { Modalize } from 'react-native-modalize';
import WebViewModalProvider, { WebViewModal } from 'react-native-webview-modal';

const Login = () => {
  const [input, setInput] = useState('');
  const [hidePass, setHidePass] = useState(true);
  const [ischecked1, setIschecked1] = useState(true);
  const [webViewVisible, setWebViewVisible] = useState(false);
  const navigation = useNavigation();
  const modalizeRef = useRef(null);

  function onOpen() {
    modalizeRef.current?.open();
    setWebViewVisible(true);
  }

  function onClose() {
    modalizeRef.current?.close();
    setWebViewVisible(false);
  }

  return (
    <WebViewModalProvider>
      <KeyboardAvoidingView style={styles.container}>
        <SafeAreaView>
          <Modalize
            ref={modalizeRef}
            snapPoint={500}
            onClosed={onClose}
          >
            <View style={{
              flex: 1,
              height: 500,
              alignItems: 'center',
              justifyContent: 'center'
            }}>
              <View style={{ margin: 30, height: '100%', width: '100%' }}>
                <WebViewModal
                  visible={webViewVisible}
                  source={{ uri: "https://account.activedirectory.windowsazure.com/ChangePassword.aspx" }}
                  style={{ flex: 1, margin: 10 }}
                />
              </View>
            </View>
          </Modalize>

          <ScrollView style={{ flex: 1 }}>
            <Image
              source={require('../../assets/logo.png')}
              style={styles.logo}
            />
            <Text style={styles.helloText}>
              Olá de novo !
            </Text>
            <Text style={styles.welcomeText}>
              Bem-vindo(a) de volta,
              sentimos sua falta!
            </Text>

            <TextInput
              style={styles.inputArea}
              placeholder="Digite o e-mail"
            />
            <TextInput
              style={styles.inputArea}
              placeholder="Senha"
              value={input}
              onChangeText={(texto) => setInput(texto)}
              secureTextEntry={hidePass}
            />
            <TouchableOpacity style={styles.eye} onPress={() => setHidePass(!hidePass)}>
              <Ionicons name={hidePass ? 'eye' : 'eye-off'}
                color="#A0D800" size={25}
              />
            </TouchableOpacity>
            <View style={styles.checkBoxStyle}>
              <CheckBox
                left
                size={18}
                checkedColor='#A0D800'
                value={ischecked1}
                checked={ischecked1}
                onPress={() => setIschecked1(!ischecked1)}
                containerStyle={{
                  backgroundColor: "transparent",
                  borderColor: "transparent", marginRight: 0
                }}
              />
              <TouchableOpacity onPress={() => setIschecked1(true)}>
                <Text style={styles.Connected}>
                  Manter-se conectado
                </Text>
              </TouchableOpacity>

              <TouchableOpacity onPress={onOpen}>
                <Text style={styles.forgotPassword}>
                  Esqueci minha senha
                </Text>
              </TouchableOpacity>
            </View>

            <TouchableOpacity
              style={styles.botao}
              onPress={() => navigation.navigate("TabNavigator")}
            >
              <Text style={styles.botaoText}>Entrar</Text>
            </TouchableOpacity>
          </ScrollView>
        </SafeAreaView>
      </KeyboardAvoidingView>
    </WebViewModalProvider>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff'
  },
  logo: {
    marginTop: 50,
    marginBottom: 80,
    width: 150,
    height: 40,
  },
  inputArea: {
    marginTop: 30,
    padding: 15,
    height: 60,
    width: 370,
    borderColor: '#808080',
    borderWidth: 1,
    backgroundColor: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
    borderRadius: 15
  },
  botao: {
    width: 350,
    height: 60,
    backgroundColor: '#000000',
    marginTop: 35,
    marginLeft: 8,
    borderRadius: 15,
    alignItems: 'center',
    justifyContent: 'center',
  },
  botaoText: {
    fontSize: 15,
    fontWeight: 'bold',
    color: '#fff'
  },
  helloText: {
    fontSize: 40,
    fontWeight: 'bold',
    marginTop: 15,
    color: '#000000',
    marginEnd: 120,
    marginTop: 8
  },
  welcomeText: {
    fontSize: 16,
    marginTop: 10,
    marginEnd: 35,
    marginVertical: 10,
    color: '#808080',
  },
  forgotPassword: {
    textDecorationLine: 'underline',
    fontWeight: 'bold',
    marginTop: 15,
    marginBottom: 15,
    marginLeft: 30,
    fontSize: 12
  },
  Connected: {
    textDecorationLine: 'underline',
    fontWeight: 'bold',
    marginTop: 15,
    fontSize: 12,
    marginRight: 55,
    marginLeft: -5
  },
  checkBoxStyle: {
    marginTop: 15,
    flexDirection: 'row',
    marginStart: -10
  },
  eye: {
    alignSelf: 'flex-end',
    bottom: 42,
    right: 40
  }
})

export default Login;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:55:27