添加React Navigation后TextInput无法输入的问题求助
核心问题分析
- 嵌套组件重复创建:你在
App组件内部定义HomeScreen、RegisterScreen,每次App组件重新渲染时,这些屏幕组件都会被重新定义,导致组件频繁卸载再挂载,输入框内容被重置,看起来无法输入。 - 函数定义错误:
loginWithFirebase用类组件的方法赋值方式(loginWithFirebase = () => {}),在函数组件中这种写法不规范,会导致作用域和绑定问题。 - 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
相关产品推荐
相关产品推荐

