React Ignite、SignupScreen、提交后未转换到欢迎屏幕/身份验证

问题描述 投票:0回答:1

我正在使用 React Ignite 样板并使用 firebase 作为后端/身份验证。当我在注册屏幕中点击“提交”时,会在 Firebase 控制台中创建该帐户,我可以点击登录按钮,然后成功登录。不过,我希望当我点击注册(并且成功)时,我会切换到欢迎屏幕并通过身份验证。

这是完整的注册屏幕。

import { observer } from "mobx-react-lite"
import React, { ComponentType, FC, useEffect, useMemo, useRef, useState } from "react"
import { Alert, TextInput, TextStyle, TouchableOpacity, ViewStyle } from "react-native"
import { Button, Icon, Screen, Text, TextField, TextFieldAccessoryProps } 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 {
        // Handle any other types of errors or objects
        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(() => {
    // Here is where you could fetch credentials from keychain or storage
    // and pre-fill the form fields.
    setAuthEmail("[email protected]")
    setAuthPassword("ign1teIsAwes0m3")

    // Return a "cleanup" function that React will run when the component unmounts
    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 accoount ? 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} />
        </>
    )}

所以我假设注册后我需要对新用户进行身份验证,然后导航到欢迎屏幕,因此我在电话号码行后面添加了以下内容

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

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

但是当我在电话号码后添加任何内容时,我就在线上遇到了未捕获的异常,我尝试添加 console.log 并且控制台中也没有任何内容。看来我无法在不破坏屏幕的情况下进行编辑...

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

感谢您的帮助

react-native react-typescript
1个回答
0
投票

从代码来看,我强烈建议删除

$
符号,尤其是在变量的开头。它可能会导致解析问题。这很可能就是正在发生的事情。

  1. 应用程序在初始捆绑包下载或完全刷新时启动/加载。
  2. 保存时应用程序失败。

这些症状听起来像是“实时重新加载”问题,其中更新的代码已损坏。

其他看起来很奇怪的部分在这里。本节在卸载时调用setState。这是一个 NO-OP/理论上什么也不做。但在实时重新加载期间,它可能会导致先前的组件实例(被拆除)在内存中保留更长时间。

useEffect(() => {
   // Return a "cleanup" function that React will run when the component unmounts
    return () => {
      setAuthPassword("")
      setAuthEmail("")
    }
  }, [])

建议

  1. 删除代码前缀的所有
    $
    变量引用。这可能不是问题。但为了获得最佳实践,我强烈建议避免这种命名结构。
  2. 关闭实时重新加载。看看是否有效。如果有可能那就是问题所在。再次打开实时重新加载,只需翻转它即可确认保存不会造成其他副作用。
  3. 检查 nodejs 内存 确认您有足够的内存。确认您配置了足够的旧空间。通常,仅对于 Metro 服务器来说,好的数字是 4GB 以上。
  4. 查看您的屏幕组件(在本示例上方)正在做什么。应用程序刷新时它们是否会触发方法?与 mobx 相同。观察者是否触发实时重新加载。
  5. 记住整个组件。查看父级是否触发重新渲染/无限冻结。
  6. 添加日志并逐步调试以查看反应线程是否实际上被冻结或者是否发生其他情况,例如透明视图阻止触摸。
© www.soinside.com 2019 - 2024. All rights reserved.