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

添加React Navigation后TextInput无法输入的问题求助

问题解决:React Native集成React Navigation后TextInput无法输入+状态值undefined

核心问题分析

  1. 嵌套组件重复创建:你在App组件内部定义HomeScreen、RegisterScreen,每次App组件重新渲染时,这些屏幕组件都会被重新定义,导致组件频繁卸载再挂载,输入框内容被重置,看起来无法输入。
  2. 函数定义错误:loginWithFirebase用类组件的方法赋值方式(loginWithFirebase = () => {}),在函数组件中这种写法不规范,会导致作用域和绑定问题。
  3. onChange事件取值错误:React Native的TextInput的onChange事件对象和Web端不同,e.target.value是undefined,正确取值应为e.nativeEvent.text,但更推荐用onChangeText直接获取输入值。

修复后的代码示例

import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import { View, TextInput, Text, Button, Alert, StyleSheet } from 'react-native';
import { db, firestore, auth } from './firebaseConfig';
import { createUserWithEmailAndPassword, signOut, signInWithEmailAndPassword } from 'firebase/auth';
import { ref, set, get, onValue, Database } from 'firebase/database';
import { doc, setDoc, getDoc, onSnapshot } from 'firebase/firestore';

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

// 把屏幕组件移到App组件外部,避免重复创建
const HomeScreen = ({ navigation, setLoginEmail, setLoginPassword, loginWithFirebase }) => {
  return (
    <View style={styles.container}>
      <View>
        <Text>Sign in with Firebase</Text>
        <TextInput
          onChangeText={value => setLoginEmail(value)}
          autoCapitalize='none'
          autoCorrect={false}
          keyboardType='email-address'
          placeholder='Email'
          style={styles.textInput}
        />
        <TextInput
          onChangeText={value => setLoginPassword(value)}
          autoCapitalize='none'
          autoCorrect={false}
          keyboardType='visible-password'
          placeholder='Password'
          secureTextEntry={true}
          style={styles.textInput}
        />
        <View style={styles.buttonContainer}>
          <Button style={styles.button} title="Login" onPress={() => loginWithFirebase(navigation)} />
        </View>

        <View style={styles.buttonContainer}>
          <Button style={styles.button} title="Register" onPress={() => navigation.navigate('Register')} />
        </View>
      </View>
    </View>
  );
};

const RegisterScreen = ({ navigation }) => {
  // 补充你的注册逻辑
  return (
    <View style={styles.container}>
      <Text>Register Screen</Text>
      <Button title="Back to Login" onPress={() => navigation.goBack()} />
    </View>
  );
};

// 假设LoginScreen是你需要的其他屏幕
const LoginScreen = ({ navigation }) => {
  return (
    <View style={styles.container}>
      <Text>Login Screen</Text>
      <Button title="Back to Home" onPress={() => navigation.goBack()} />
    </View>
  );
};

export default function App() {
  const [loginEmail, setLoginEmail] = useState('');
  const [loginPassword, setLoginPassword] = useState('');
  const [loggedIn, setLoggedIn] = useState(false);

  // 用const声明函数,符合函数组件规范
  const loginWithFirebase = (navigation) => {
    console.log(loginEmail);
    console.log(loginPassword);
    if (loginEmail.length < 4) {
      Alert.alert("Please enter a valid email address");
      return;
    }
    if (loginPassword.length < 4) {
      Alert.alert("Please enter a valid password");
      return;
    }
    // 这里补充你的Firebase登录逻辑
    signInWithEmailAndPassword(auth, loginEmail, loginPassword)
      .then((userCredential) => {
        // 登录成功逻辑
        const user = userCredential.user;
        console.log('Logged in user:', user);
      })
      .catch((error) => {
        const errorCode = error.code;
        const errorMessage = error.message;
        Alert.alert('Login Failed', errorMessage);
      });
  };

  const Stack = createNativeStackNavigator();

  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home">
          {props => <HomeScreen {...props} setLoginEmail={setLoginEmail} setLoginPassword={setLoginPassword} loginWithFirebase={loginWithFirebase} />}
        </Stack.Screen>
        <Stack.Screen name="Register" component={RegisterScreen} />
        <Stack.Screen name="Login" component={LoginScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// 补充样式定义
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 20,
  },
  textInput: {
    height: 40,
    borderColor: 'gray',
    borderWidth: 1,
    marginVertical: 10,
    paddingHorizontal: 10,
  },
  buttonContainer: {
    marginVertical: 10,
  },
});

关键修复点

  • 屏幕组件外置:将HomeScreen、RegisterScreen等移到App组件外部,避免每次App渲染都重新创建组件,解决输入框状态丢失问题。
  • 函数定义规范:用const声明loginWithFirebase函数,符合React函数组件的写法。
  • 正确传递状态方法:通过Stack.Screen的render回调,将setLoginEmail、setLoginPassword和loginWithFirebase传递给HomeScreen,确保状态作用域正确。
  • 事件处理正确:继续使用onChangeText处理输入,这是React NativeTextInput的标准用法,避免Web端的onChange取值误区。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:07:04