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

React Ignite注册成功后无法跳转至Welcome页面及认证异常

React Ignite + Firebase注册成功后无法自动认证跳转的问题

我基于React Ignite模板开发应用,使用Firebase作为后端认证服务。点击注册按钮后,Firebase控制台能成功创建用户账号,后续也能正常登录,但注册完成后系统不会自动完成认证流程并跳转到Welcome页面。

我尝试在注册逻辑中添加以下代码来实现自动认证和跳转:

const token = await user.getIdToken();
authenticationStore.setAuthToken(token); 

// Navigate to the Welcome screen
navigation.navigate("Welcome");

但添加后出现未捕获异常,程序无法正常运行。

以下是完整的SignupScreen代码及导航配置:

SignupScreen完整代码

import { observer } from "mobx-react-lite"
import React, { FC, useEffect, useState } from "react"
import { Alert, TouchableOpacity, ViewStyle, TextStyle } from "react-native"
import { Button, Screen, Text, TextField } from "../components"
import { useStores } from "../models"
import { AppStackScreenProps } from "../navigators"
import { colors, spacing } from "../theme"
import { auth, database } from "../../config/firebase";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { authenticationStore } from "../authenticationStore";
import { doc, setDoc } from "firebase/firestore"
import { useNavigation } from "@react-navigation/native"

interface SignUpScreenProps extends AppStackScreenProps<"SignUp"> { }

export const SignUpScreen: FC<SignUpScreenProps> = observer(function SignUpScreen() {

  const navigation = useNavigation()

  const goToLogin = () => {
    navigation.navigate("Login");
  }

  const onHandleSignup = async () => {
    try {
      const userCredential = await createUserWithEmailAndPassword(auth, email, password);
      const user = userCredential.user;
      const userRef = doc(database, "users", user.uid);
      await setDoc(userRef, {
        displayName: name,
        email: email,
        uid: user.uid,
        photoURL: "",
        phoneNumber: "",
      })
    } catch (error) {
      if (error instanceof Error) {
        Alert.alert(error.message);
      } else {
        Alert.alert('An unknown error occurred');
      }
    }
  };
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [imageURL, setImageURL] = useState("");


  const [authPassword, setAuthPassword] = useState("")
  const [isAuthPasswordHidden, setIsAuthPasswordHidden] = useState(true)
  const [isSubmitted, setIsSubmitted] = useState(false)
  const [attemptsCount, setAttemptsCount] = useState(0)
  const {
    authenticationStore: { authEmail, setAuthEmail, setAuthToken, validationError },
  } = useStores()

  useEffect(() => {
    setAuthEmail("ignite@infinite.red")
    setAuthPassword("ign1teIsAwes0m3")

    return () => {
      setAuthPassword("")
      setAuthEmail("")
    }
  }, [])

  return (
    <Screen
      preset="auto"
      contentContainerStyle={$screenContentContainer}
      safeAreaEdges={["top", "bottom"]}
    >
      <Text testID="login-heading" tx="signUpScreen.signIn" preset="heading" style={$signIn} />
      <Text tx="signUpScreen.enterDetails" preset="subheading" style={$enterDetails} />
      {attemptsCount > 2 && <Text tx="signUpScreen.hint" size="sm" weight="light" style={$hint} />}

      <TextField
        value={email}
        onChangeText={setEmail}
        containerStyle={$textField}
        autoCapitalize="none"
        autoComplete="email"
        autoCorrect={false}
        keyboardType="email-address"
        labelTx="signUpScreen.emailFieldLabel"
        placeholderTx="signUpScreen.emailFieldPlaceholder"
      />

      <TextField
        value={name}
        onChangeText={setName}
        containerStyle={$textField}
        autoCapitalize="none"
        autoCorrect={false}
        labelTx="signUpScreen.nameFieldLabel"
        placeholderTx="signUpScreen.nameFieldPlaceholder"
      />

      <TextField
        value={password}
        onChangeText={setPassword}
        containerStyle={$textField}
        autoCapitalize="none"
        autoComplete="password"
        autoCorrect={false}
        secureTextEntry={isAuthPasswordHidden}
        labelTx="signUpScreen.passwordFieldLabel"
        placeholderTx="signUpScreen.passwordFieldPlaceholder"
      />

      <Button
        testID="login-button"
        tx="signUpScreen.tapToSignIn"
        style={$tapButton}
        preset="reversed"
        onPress={onHandleSignup}
      />

      <TouchableOpacity style={$loginButton} onPress={goToLogin}>
        <Text>Have an account ? Login</Text>
      </TouchableOpacity>

    </Screen>
  )
})

const $screenContentContainer: ViewStyle = {
  paddingVertical: spacing.xxl,
  paddingHorizontal: spacing.lg,
}

const $signIn: TextStyle = {
  marginBottom: spacing.sm,
}

const $enterDetails: TextStyle = {
  marginBottom: spacing.lg,
}

const $hint: TextStyle = {
  color: colors.tint,
  marginBottom: spacing.md,
}

const $textField: ViewStyle = {
  marginBottom: spacing.lg,
}

const $tapButton: ViewStyle = {
  marginTop: spacing.xs,
}

const $loginButton: ViewStyle = {
  marginTop: spacing.xs,
  alignItems: 'center',
  padding: 10,
}

// @demo remove-file

导航配置代码

{isAuthenticated ? (
        <>
          {/* @demo remove-block-end */}
          <Stack.Screen name="Welcome" component={Screens.WelcomeScreen} />
          {/* @demo remove-block-start */}
          <Stack.Screen name="Demo" component={DemoNavigator} />
        </>
      ) : (
        <>
          <Stack.Screen name="Login" component={Screens.LoginScreen} />
          <Stack.Screen name="SignUp"component={Screens.SignUpScreen} />
        </>
    )}

问题修复方案

  1. 统一Store实例获取方式
    移除直接导入的authenticationStore,只用useStores()返回的实例,避免多实例导致的状态异常。

  2. 修正注册逻辑
    更新onHandleSignup函数,确保token获取、状态更新和导航操作都在try块内正确执行:

    const onHandleSignup = async () => {
      try {
        const userCredential = await createUserWithEmailAndPassword(auth, email, password);
        const user = userCredential.user;
        const userRef = doc(database, "users", user.uid);
        await setDoc(userRef, {
          displayName: name,
          email: email,
          uid: user.uid,
          photoURL: "",
          phoneNumber: "",
        });
        // 获取ID Token并更新认证状态
        const token = await user.getIdToken();
        setAuthToken(token);
        // 跳转到Welcome页面
        navigation.navigate("Welcome");
      } catch (error) {
        if (error instanceof Error) {
          Alert.alert(error.message);
        } else {
          Alert.alert('An unknown error occurred');
        }
      }
    };
    
  3. 优化Navigation使用
    组件已继承AppStackScreenProps,可直接从props解构navigation,无需调用useNavigation():

    export const SignUpScreen: FC<SignUpScreenProps> = observer(function SignUpScreen({ navigation }) {
      // 移除原有的const navigation = useNavigation()
      ...
    })
    
  4. 验证认证状态联动
    确保导航配置中的isAuthenticated是基于authenticationStore中authToken的衍生状态(比如Mobx的computed值),这样更新token后isAuthenticated会自动切换,导航栈也会同步更新。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:22:07