React Native登录页WebViewModal报错:null is not an object
问题
我开发的React Native登录页面遇到一个问题:点击「忘记密码」按钮时,本该弹出包含指定网站的Modal,但现在触发「null is not an object」错误。之前代码运行完全正常,移除WebViewModal组件后Modal能正常显示,推测问题出在WebViewModal组件上,求技术帮助。
排查与解决方案
问题根源分析
- Provider作用域错误:
WebViewModalProvider被嵌套在Modalize内部,导致WebViewModal无法正确获取上下文,引发空引用错误。 - 硬编码visible属性:
WebViewModal的visible被设为true,组件初始化时就尝试渲染,而此时Modalize尚未打开,导致WebView相关实例未正确初始化。 - 冗余布局组件:
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
相关产品推荐
相关产品推荐

