React Native条件渲染失效,咨询代码修改实现登录注册切换逻辑
修复React Native登录/注册/账户管理的条件渲染流程
问题根源
- 原代码用多个布尔状态(
showRegisterForm/afterRegister/afterLogin)组合控制视图,逻辑嵌套复杂,容易出现状态冲突导致显示异常。 - 登录逻辑中无论请求是否成功,都直接设置
afterLogin=true,不符合预期流程。 - 注册成功后仅设置
afterRegister=true,未重置注册表单状态,无法正确切回登录视图。
修改方案
改用单一状态currentView控制当前显示的视图,取值为'login'/'register'/'account',简化状态逻辑;同时修正登录、注册的状态切换逻辑,确保流程符合预期。
修改后的完整代码
import { StyleSheet, Button } from 'react-native'; import React, { useState } from 'react'; import { View, TextInput, TouchableOpacity, Linking } from 'react-native'; import { Text } from '../../components/Themed'; import axios from 'axios'; import { Constants } from '../../constants/Constants'; import AsyncStorage from '@react-native-async-storage/async-storage'; export default function TabOneScreen() { // 登录表单状态 const [email, setEmail] = useState("") const [password, setPassword] = useState("") // 注册表单状态 const [firstName, setFirstName] = useState("") const [lastName, setLastName] = useState("") const [userEmail, setUserEmail] = useState("") const [userPassword, setUserPassword] = useState("") const [confirmPassword, setConfirmPassword] = useState("") const [stripeConnectAcctId, setStripeConnectAcctId] = useState("") // 控制当前显示的视图:'login' | 'register' | 'account' const [currentView, setCurrentView] = useState('login') const subdomain = Constants.Subdomain; const onPressLogin = async () => { try { const req_json2 = { username: email, password: password, grant_type: 'password' } const headers2 = { headers: { "Accept": "*/*", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Cache-Control": "no-cache", "Host": `${subdomain}.conveyor.cloud` } }; const resp = await axios.post(`https://${subdomain}.conveyor.cloud/token`, req_json2, headers2); const token = resp.data.access_token; if (token && token !== "") { console.log("auth_token: " + token); await AsyncStorage.setItem('auth_token', token); await AsyncStorage.setItem('senderEmail', email); // 登录成功,切换到账户管理视图 setCurrentView('account') } } catch (err) { console.error('登录失败:', err) // 可添加错误提示逻辑 } } const stripeOnboarding = async () => { try { const auth_token = await AsyncStorage.getItem('auth_token'); const headers = { headers: { "Authorization": `Bearer ${auth_token}`, "Accept": "*/*", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Cache-Control": "no-cache", "Host": `${subdomain}.conveyor.cloud` } }; const resp = await axios.post(`https://${subdomain}.conveyor.cloud/Home/CreateStripeAccount`, {}, headers); console.log(resp.data.connectedAccountId, resp.data.onboardingUrl) if (resp) { setStripeConnectAcctId(resp.data.connectedAccountId); const senderEmail = await AsyncStorage.getItem('senderEmail'); const req_json = { email: senderEmail, stripeConnectedAcctId: resp.data.connectedAccountId }; const headers2 = { headers: { "Authorization": `Bearer ${auth_token}`, "Accept": "*/*", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Cache-Control": "no-cache", "Host": `${subdomain}.conveyor.cloud` } }; await axios.post(`https://${subdomain}.conveyor.cloud/Account/SaveStripeAcctId`, req_json, headers2); if (await Linking.canOpenURL(resp.data.onboardingUrl)) { await Linking.openURL(resp.data.onboardingUrl); } } } catch (err) { console.error('Stripe连接失败:', err) } } const submitRegistrationForm = async () => { try { const req_json = { FirstName: firstName, LastName: lastName, Email: userEmail, Password: userPassword, ConfirmPassword: confirmPassword } const headers = { headers: { "Accept": "*/*", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Cache-Control": "no-cache", "Host": `${subdomain}.conveyor.cloud` } }; await axios.post(`https://${subdomain}.conveyor.cloud/Account/Register`, req_json, headers); // 注册成功,重置表单并切回登录视图 setFirstName("") setLastName("") setUserEmail("") setUserPassword("") setConfirmPassword("") setCurrentView('login') } catch (err) { console.error('注册失败:', err) // 可添加错误提示逻辑 } } // 根据currentView渲染对应组件 const renderView = () => { switch (currentView) { case 'login': return ( <View style={styles.container}> <View style={styles.inputView}> <TextInput style={styles.inputText} placeholder="Email" placeholderTextColor="#003f5c" onChangeText={(text) => setEmail(text)} value={email} /> </View> <View style={styles.inputView}> <TextInput style={styles.inputText} secureTextEntry placeholder="Password" placeholderTextColor="#003f5c" onChangeText={(text) => setPassword(text)} value={password} /> </View> <View style={styles.inputView}> <TouchableOpacity onPress={onPressLogin} style={styles.loginBtn}> <Text>Log in.</Text> </TouchableOpacity> </View> <View> <Button onPress={() => setCurrentView('register')} style={styles.registerBtn} title='Register' /> </View> </View> ) case 'register': return ( <View style={styles.container}> <Text>Registration Form.</Text> <TextInput placeholder='First name' onChangeText={text => setFirstName(text)} style={styles.registerFormField} value={firstName}></TextInput> <TextInput placeholder='Last name' onChangeText={text => setLastName(text)} style={styles.registerFormField} value={lastName}></TextInput> <TextInput placeholder='Email address' onChangeText={text => setUserEmail(text)} style={styles.registerFormField} value={userEmail}></TextInput> <TextInput placeholder='Password' onChangeText={text => setUserPassword(text)} style={styles.registerFormField} secureTextEntry value={userPassword}></TextInput> <TextInput placeholder='Confirm password' onChangeText={text => setConfirmPassword(text)} style={styles.registerFormField} secureTextEntry value={confirmPassword}></TextInput> <Button onPress={submitRegistrationForm} title='Register'/> {/* 可选:添加返回登录按钮 */} <Button onPress={() => setCurrentView('login')} title='Back to Login' style={{ marginTop: 10 }}/> </View> ) case 'account': return ( <View style={styles.container}> <Text>Manage Account.</Text> <Button onPress={stripeOnboarding} title='Connect with Stripe'/> </View> ) default: return null } } return renderView() }; const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 20 }, inputView:{ width:"80%", backgroundColor:"#3AB4BA", borderRadius:25, height:50, marginBottom:20, justifyContent:"center", padding:20 }, inputText:{ height:50, color:"white" }, loginBtn: { alignItems: 'center', justifyContent: 'center', width: '100%' }, registerBtn: { marginTop:35, padding:8, borderColor:'black', borderWidth:2, borderRadius:5 }, registerFormField: { width: '100%', margin:8, borderColor: 'black', borderWidth: 2, padding:10, borderRadius: 5 } });
关键修改点
- 用
currentView单一状态替代多个布尔状态,逻辑更清晰,避免状态冲突。 - 登录逻辑中仅在成功获取token后切换到账户视图,添加错误捕获。
- 注册成功后重置表单输入值,并切换回登录视图。
- 拆分渲染逻辑到
renderView函数,用switch-case实现条件渲染,可读性更强。 - 给TextInput添加
value属性,确保表单输入受控。 - 优化Stripe逻辑中的AsyncStorage调用,添加
await确保获取到token。
内容的提问来源于stack exchange,提问作者xccelerated99
相关产品推荐
相关产品推荐

