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

React Native跳转注册页报props.route未定义TypeError修复

报错根因
  • 组件参数解构错误:React Navigation 向注册页面传入的顶层props仅包含navigation、route属性,SignUpScreen中写的({navigation,route,props})相当于尝试从props中解构不存在的props字段,后续访问props.route时自然拿到undefined。
  • 跳转时未传参:Main页面点击「Dont have an account ?」跳转时,没有向SignUpScreen传递type参数,即使props写法正确,访问route.params.type也会因为params为空报错。
  • 逻辑写法无效:Main页面Doctor、User按钮的onPress使用逗号表达式,既没有保存选中的用户身份,也没有传递参数,完全不生效;且页面缺少邮箱、密码输入框,原有登录逻辑根本无法获取输入值。
  • 页面分支缺失:SignUpScreen仅写了type=='Doctor'时的返回UI,普通用户身份进入页面时会出现白屏;接口请求异常时未重置loading状态,会导致页面永久卡死在加载态。
代码修复方案

1. 修正SignUpScreen代码

首先修正组件入参,移除不存在的props解构项,给参数加空值保护,补全普通用户分支,修正所有错误的props引用:

import React,{useState, useEffect} from 'react'
import { View, Text ,Image,StyleSheet,KeyboardAvoidingView,TouchableOpacity,ActivityIndicator,ScrollView} from 'react-native'
import { TextInput,Button } from 'react-native-paper';
import {launchImageLibrary} from 'react-native-image-picker';
import storage from '@react-native-firebase/storage'
import auth from '@react-native-firebase/auth'
import firestore from '@react-native-firebase/firestore'

// 组件入参直接解构navigation和route,不要加多余的props字段
const SignupScreen =({navigation,route}) =>{
    const [email,setEmail] = useState('')
    const [name,setName] = useState('')
    const [password,setPassword] = useState('')
    const [image,setImage] = useState(null)
    const [showNext,setShowNext] = useState(false)
    const [loading,setLoading] = useState(false)
    
    if(loading){
        return  <ActivityIndicator size="large" color="#00ff00" />
    }
    const userSignup = async ()=>{
        setLoading(true)
        if(!email || !password || !name){
               alert("please add all the field")
               setLoading(false)
               return 
        }
        try{
          const result =  await auth().createUserWithEmailAndPassword(email,password)
            firestore().collection('users').doc(result.user.uid).set({
                name:name,
                email:result.user.email,
                uid:result.user.uid,
                pic:image,
                status:"online",
                type: type
            })  
            setLoading(false)
        }catch(err){
            setLoading(false)
            alert("something went wrong")
        }
    }
    // 用可选链做安全访问,设置默认值为普通用户,避免参数缺失时报错
    const type=route?.params?.type || 'User'

     useEffect(()=>{
     // 原代码调用了未定义的allUsers函数,需自行补全对应逻辑
     // allUsers()
 },[])
    
 // 医生端注册UI
 if(type=='Doctor'){
 return (
     <ScrollView>
        <KeyboardAvoidingView behavior="position">
            <View style={styles.box1}>
                <Image style={styles.img} source={require('../assets/hee.png')} />
            </View>
            <View style={styles.box2}>
                {!showNext && 
                <>
                 <TextInput
                 label="Email"
                 value={email}
                 onChangeText={(text)=>setEmail(text)}
                 mode="outlined"
                />
                <TextInput
                 label="password"
                 mode="outlined"
                 value={password}
                 onChangeText={(text)=>setPassword(text)}
                 secureTextEntry
                />
                 <TextInput
                 label="Full Name"
                 mode="outlined"
                />
                 <TextInput
                 label="Address"
                 mode="outlined"
                />
                 <TextInput
                 label="Contact Number"
                 mode="outlined"
                 keyboardType='numeric'
                />
                </>
                }
               
               {showNext ?
                <>
                 <TextInput
                 label="Name"
                 value={name}
                 onChangeText={(text)=>setName(text)}
                 mode="outlined"
                />
                
                <Button
                mode="contained"
                style={{marginTop:20}}
                onPress={()=>userSignup()}
                >Signup</Button>

               <TouchableOpacity style={{textAlign:"center", marginTop:25,marginLeft:115}} onPress={()=>navigation.goBack()}>
                   <Text>Go Back</Text>
               </TouchableOpacity>
                </>
                :
                 <Button
                 style={{marginTop:20}}
                mode="contained"
                onPress={()=>setShowNext(true)}
                >Next</Button>
                }
              {/* 替换原错误的props.navigation引用 */}
              <TouchableOpacity onPress={()=>navigation.goBack()}><Text style={{textAlign:"center", marginTop:25}}>Already have an account ?</Text></TouchableOpacity>
            </View>
        </KeyboardAvoidingView>
        </ScrollView>
    )
}
// 补全普通用户注册UI,可根据业务需求增减字段
return (
     <ScrollView>
        <KeyboardAvoidingView behavior="position">
            <View style={styles.box1}>
                <Image style={styles.img} source={require('../assets/hee.png')} />
            </View>
            <View style={styles.box2}>
                <TextInput
                label="Email"
                value={email}
                onChangeText={(text)=>setEmail(text)}
                mode="outlined"
                />
                <TextInput
                 label="password"
                 mode="outlined"
                 value={password}
                 onChangeText={(text)=>setPassword(text)}
                 secureTextEntry
                />
                <TextInput
                 label="Full Name"
                 value={name}
                 onChangeText={(text)=>setName(text)}
                 mode="outlined"
                />
                <Button
                mode="contained"
                style={{marginTop:20}}
                onPress={()=>userSignup()}
                >Signup</Button>
                <TouchableOpacity onPress={()=>navigation.goBack()}><Text style={{textAlign:"center", marginTop:25}}>Already have an account ?</Text></TouchableOpacity>
            </View>
        </KeyboardAvoidingView>
    </ScrollView>
)
}

export default SignupScreen

const styles = StyleSheet.create({
    text:{
        fontSize:22,
        color:"green",
        margin:15
    },
    img:{
        width:250,
        height:250
    },
    box1:{
        alignItems:"center"
    },
    box2:{
    width:"70%",
        justifyContent:"center",
        height:"50%",
        margin:20,
        marginLeft:55
    }
 });

2. 修正Main页面代码

增加状态存储选中的用户类型,补全输入框渲染,修正按钮逻辑,跳转注册页时传递type参数:

import React,{useState} from 'react'
import { View, Text ,Image,StyleSheet,KeyboardAvoidingView,TouchableOpacity,ActivityIndicator} from 'react-native'
import { TextInput,Button } from 'react-native-paper';
import auth from '@react-native-firebase/auth'


const Main =props=> {
    const [email,setEmail] = useState('')
    const [password,setPassword] = useState('')
    const [loading,setLoading] = useState(false)
    // 新增状态存储当前选中的用户类型,默认普通用户
    const [selectedType,setSelectedType] = useState('User')

    if(loading){
        return  <ActivityIndicator size="large" color="red" />
    }
    const userLogin = async ()=>{
        setLoading(true)
        if(!email || !password){
               alert("please add all the field")
               setLoading(false)
               return 
        }
        try{
          const result =  await auth().signInWithEmailAndPassword(email,password)
          // 登录后可查询用户表中存储的type字段,跳转到对应身份的首页
            setLoading(false)
        }catch(err){
            setLoading(false)
            alert("something went wrong")
        }
    }
    return (
        <KeyboardAvoidingView behavior="position">
            <View style={styles.box1}>
                <Image style={styles.img} source={require('../assets/hee.png')} />
            </View>
            <View style={styles.box2}>
                 <TextInput
                 label="Email"
                 value={email}
                 onChangeText={(text)=>setEmail(text)}
                 mode="outlined"
                />
                <TextInput
                 label="password"
                 mode="outlined"
                 value={password}
                 onChangeText={(text)=>setPassword(text)}
                 secureTextEntry
                />
                 <Button
                mode="contained"
                onPress={()=>{
                    setSelectedType('Doctor')
                    userLogin()
                }}
                >Doctor</Button>
                
                 <Button
                mode="contained"
                onPress={()=>{
                    setSelectedType('User')
                    userLogin()
                }}
                >User</Button>
                <TouchableOpacity 
                // 跳转时传递选中的用户类型
                onPress={()=>props.navigation.navigate('signup',{type: selectedType})}>
                    <Text style={{textAlign:"center"}}>Dont have an account ?</Text>
                </TouchableOpacity>
               
            </View>
        </KeyboardAvoidingView>
    )
}

export default Main
const styles = StyleSheet.create({
    text:{
        fontSize:22,
        color:"red",
        margin:10
    },
    img:{
        width:250,
        height:250
    },
    box1:{
        alignItems:"center"
    },
    box2:{
        paddingHorizontal:40,
        justifyContent:"space-evenly",
        height:"50%"
    }
 });
不依赖页面props传参的替代方案
  • 全局状态管理:使用React Context、Zustand、Redux等全局状态方案,在Main页面选中用户类型后存入全局store,SignUpScreen直接从全局store读取身份值,完全不需要依赖路由传参,适合多页面共享身份状态的场景。
  • 本地缓存存储:选中用户类型后通过@react-native-async-storage/async-storage将类型值存在本地,SignUpScreen渲染时直接读取本地缓存的类型,就算应用重启、深链进入页面也不会丢失参数。
  • 多路由配置:给医生、普通用户的注册页配置两个独立的路由名(如DoctorSignup、UserSignup),两个路由可指向同一个SignUpScreen组件,跳转时直接跳对应路由即可,不需要额外传参,路由语义更清晰。
  • 导航封装校验:封装统一的导航跳转工具函数,强制要求跳转到SignUpScreen时必须传入type参数,结合TypeScript类型校验可以从根源上避免漏传参数的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:03:27