React Native WebView Modal Error - Null Object Issue in Authentication Screen

I’m having trouble with my React Native authentication screen and need some help.

I built a login form that shows a modal with a webview when users tap “forgot password”. Everything was working fine before, but now I keep getting a “null is not an object” error. The weird thing is that if I remove the WebViewModal component, the modal shows up without any problems. So I think the issue is somewhere in the WebViewModal setup.

Has anyone run into this before? I’m not sure what changed to break it.

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

const AuthScreen = () => {
    const [passwordText, setPasswordText] = useState('');
    const [showPassword, setShowPassword] = useState(false);
    const [rememberMe, setRememberMe] = useState(false);
    const [modalVisible, setModalVisible] = useState(false);
    const navigation = useNavigation();
    const modalRef = useRef(null);

    const openModal = () => {
        modalRef.current?.open();
    };

    return (
        <KeyboardAvoidingView style={styles.wrapper}>
            <SafeAreaView>
                <Modalize
                    ref={modalRef}
                    snapPoint={450}
                >
                    <View style={{
                        flex: 1, height: 450,
                        flexDirection: 'column', alignItems: 'center'
                    }}>
                        <WebViewModalProvider>
                            <View style={{ padding: 20, height: 450 }}>
                                <SafeAreaView />
                                <WebViewModal
                                    visible={true}
                                    source={{ uri: "https://myapp.com/reset-password" }}
                                    style={{ padding: 15 }}
                                />
                            </View>
                        </WebViewModalProvider>
                    </View>
                </Modalize>

                <ScrollView style={{ flex: 1 }}>
                    <Image
                        source={require('../../images/brand-logo.png')}
                        style={styles.brandLogo}
                    />
                    <Text style={styles.titleText}>
                        Welcome Back!
                    </Text>
                    <Text style={styles.subtitleText}>
                        Please sign in to continue
                    </Text>

                    <TextInput
                        style={styles.textField}
                        placeholder="Enter your email"
                    />
                    <TextInput
                        style={styles.textField}
                        placeholder="Password"
                        value={passwordText}
                        onChangeText={(text) => setPasswordText(text)}
                        secureTextEntry={!showPassword}
                    />
                    <TouchableOpacity 
                        style={styles.eyeIcon} 
                        onPress={() => setShowPassword(!showPassword)}
                    >
                        <MaterialIcons 
                            name={showPassword ? 'visibility' : 'visibility-off'}
                            color="#00AA55" 
                            size={24}
                        />
                    </TouchableOpacity>

                    <View style={styles.optionsRow}>
                        <CheckBox
                            left
                            size={16}
                            checkedColor='#00AA55'
                            value={rememberMe}
                            checked={rememberMe}
                            onPress={() => setRememberMe(!rememberMe)}
                            containerStyle={{
                                backgroundColor: "transparent",
                                borderColor: "transparent"
                            }}
                        />
                        <TouchableOpacity onPress={() => setRememberMe(true)}>
                            <Text style={styles.rememberText}>
                                Remember me
                            </Text>
                        </TouchableOpacity>

                        <TouchableOpacity onPress={openModal}>
                            <Text style={styles.resetLink}>
                                Reset password
                            </Text>
                        </TouchableOpacity>
                    </View>

                    <TouchableOpacity
                        style={styles.submitButton}
                        onPress={() => navigation.navigate("MainTabs")}
                    >
                        <Text style={styles.submitText}>Sign In</Text>
                    </TouchableOpacity>
                </ScrollView>
            </SafeAreaView>
        </KeyboardAvoidingView>
    );
};

const styles = StyleSheet.create({
    wrapper: {
        flex: 1,
        backgroundColor: '#ffffff'
    },
    brandLogo: {
        marginTop: 40,
        marginBottom: 60,
        width: 140,
        height: 35
    },
    textField: {
        marginTop: 25,
        padding: 18,
        height: 55,
        width: 360,
        borderColor: '#cccccc',
        borderWidth: 1,
        backgroundColor: '#fff',
        fontSize: 15,
        borderRadius: 12
    },
    submitButton: {
        width: 340,
        height: 55,
        backgroundColor: '#333333',
        marginTop: 30,
        marginLeft: 10,
        borderRadius: 12,
        alignItems: 'center',
        justifyContent: 'center'
    },
    submitText: {
        fontSize: 16,
        fontWeight: 'bold',
        color: '#ffffff'
    },
    titleText: {
        fontSize: 36,
        fontWeight: 'bold',
        color: '#000000',
        marginBottom: 5
    },
    subtitleText: {
        fontSize: 15,
        marginTop: 8,
        color: '#666666'
    },
    resetLink: {
        textDecorationLine: 'underline',
        fontWeight: 'bold',
        marginTop: 12,
        fontSize: 13,
        marginLeft: 40
    },
    rememberText: {
        textDecorationLine: 'underline',
        fontWeight: 'bold',
        marginTop: 12,
        fontSize: 13,
        marginRight: 60
    },
    optionsRow: {
        marginTop: 20,
        flexDirection: 'row'
    },
    eyeIcon: {
        alignSelf: 'flex-end',
        bottom: 38,
        right: 35
    }
});

export default AuthScreen;

what error messages are you seeing in the console? that “null is not an object” error usually means WebViewModal is trying to access properties before its ready. try adding error boundaries or check if the webview source loads correctly. which version of react-native-webview-modal are you running?

you’re rendering a modal inside another modal - that’s what’s causin the null reference. your WebViewModal has visible={true} but there’s no state management behind it. drop the WebViewModalProvider wrapper and just use a regular WebView component from react-native-webview. Modalize is already handlin the modal stuff for you.

I had the same issue recently. The problem is that WebViewModal doesn’t play nice with other modal components - it messes up the internal state when nested inside Modalize containers. The react-native-webview-modal library just conflicts with Modalize. Here’s what worked for me: ditch WebViewModal completely and use a regular WebView from react-native-webview instead. Since your Modalize is already working fine, just drop a standard WebView inside it. Get rid of the WebViewModalProvider wrapper too. This kills the conflicting modal layers but keeps your password reset flow working exactly the same.