在 apk 构建中单击提交按钮后显示不需要的启动画面

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

当我在 Expo Go 上测试我的应用程序时,我完全没有收到任何错误,并且我的应用程序运行良好。在创建构建时,当我尝试登录并单击登录按钮时,应用程序突然进入 SplashScreen。注册页面上也会发生同样的情况。我已经能够推断出异步请求会触发此问题。也就是说,我仍然不知道如何去做。这特别难以调试,因为它只出现在 APK 版本中。我正在使用 expo 和 expo 路由器。

app/index.tsx(登录页面)

import loginApi from "@/api/login";
import { useAuthContext } from "@/auth/context";
import { ThemedText } from "@/components/ThemedText";
import AppForm from "@/components/forms/AppForm";
import AppFormField from "@/components/forms/AppFormField";
import SubmitButton from "@/components/forms/SubmitButton";
import { Colors } from "@/constants/Colors";
import useApi from "@/hooks/useApi";
import Constants from "expo-constants";
import { Link } from "expo-router";
import { X } from "lucide-react-native";
import { useState } from "react";
import { ActivityIndicator, Image, StyleSheet, Text, View } from "react-native";
import * as Yup from "yup";
import * as SplashScreen from 'expo-splash-screen';

export interface UserCredentials {
  email: string;
  password: string;
}

export default function index() {
  const { login,showNotification } = useAuthContext();
  const [loginFailed, setLoginFailed] = useState<boolean>(false);

  const validationSchema = Yup.object().shape({
    email: Yup.string().required().email().label("Email"),
    password: Yup.string().required().min(4).label("Password"),
  });
  const {
    loading,
    request: loginRequest,
  } = useApi(loginApi.getLogin);

  const handleSubmit = async({ email, password }: UserCredentials) => {
    const data = { email, password };
    setLoginFailed(false);
    try {
      const response = await loginRequest(data);
      SplashScreen.hideAsync()
      if (response && response.status === 200) {
        login(response.data);
      } else {
        SplashScreen.hideAsync()
        console.log(response.data.non_field_errors);
        showNotification(`Login failed. ${response.data.non_field_errors[0]}`, <X size={16} color="red" fill={"red"} />);
        setLoginFailed(true);
      }
    } catch (error: any) {
      if (error.response && error.response.data) {
        const nonFieldErrors = error.response.data.non_field_errors;
        if (nonFieldErrors && nonFieldErrors.length > 0) {
          showNotification(nonFieldErrors[0], <X size={16} color="red" fill={"red"} />);
        } else {
          showNotification(`Login failed. Please try again. ${error.response.data}`, <X size={16} color="red" fill={"red"} />);
        }
      } else {
        showNotification(`Login failed. Please try again. ${error.message}`, <X size={16} color="red" fill={"red"} />);
      }
      setLoginFailed(true);
    }
  };


  return (
    <View style={styles.Screen}>
      <View style={styles.Top}>
        <Image
          source={require("../assets/images/HopterlinkLogo.png")}
          style={{ width: 150, height: 150, marginTop: 50 }}
          resizeMethod="resize"
          resizeMode="contain"
        />
      </View>
      <View style={{ paddingTop: 30 }}>
        <ThemedText
          darkColor="#000000"
          type="title"
          style={{ fontSize: 20, fontWeight: "800" }}
        >
          Sign In
        </ThemedText>
        <View>
          <AppForm
            initialValues={{ email: "", password: "" }}
            onSubmit={handleSubmit}
            validationSchema={validationSchema}
          >
            <AppFormField
              name="email"
              icon="mail"
              style={{ marginTop: 10 }}
              placeholder="Email"
              keyboardType="email-address"
            />
            <AppFormField
              name="password"
              icon="lock"
              style={{ marginTop: 10 }}
              placeholder="Password"
              secureTextEntry={true}
            />
            <Text
              style={{
                color: Colors.primary,
                textAlign: "right",
                marginTop: 10,
                fontWeight: "bold",
                fontSize: 12,
              }}
            >
              Forgot Password?
            </Text>
            {loading ? (
              <View>
                <ActivityIndicator color={Colors.primary} size={"small"} style={{ marginVertical: 20 }} />
              </View>
            ) : (
              <SubmitButton title="Sign In" />
            )}
          </AppForm>
          {loginFailed && (
            <Text style={{ color: 'red', textAlign: 'center', marginTop: 10 }}>
              Login failed. Please try again.
            </Text>
          )}
        </View>
      </View>
      <View style={{ marginTop: 20 }}>
        <Text
          style={{
            color: "rgba(166, 166, 166, 0.6)",
            textAlign: "center",
            marginTop: 10,
            fontWeight: "bold",
            fontSize: 14,
          }}
        >
          Don’t have an account?{" "}
          <Link style={{ color: Colors.primary }} href="/sign-up">
            Sign Up
          </Link>
        </Text>
        <View>
          <Text
            style={{
              marginTop: 20,
              textAlign: "center",
              fontWeight: "bold",
              fontSize: 14,
            }}
          >
            Social Login
          </Text>
        </View>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  Screen: {
    flex: 1,
    backgroundColor: Colors.light.background,
    paddingHorizontal: 10,
    paddingTop: Constants.statusBarHeight,
  },
  Top: {
    flex: 0.5,
    alignItems: "center",
    justifyContent: "center",
  },
  button: {
    width: "100%",
    padding: 15,
    marginTop: 40,
    backgroundColor: Colors.primary,
    borderRadius: 10,
    justifyContent: "center",
    alignItems: "center",
    marginVertical: 10,
  },
});

应用程序/_layout.tsx

import { AuthProvider, useAuthContext } from "@/auth/context";
import OfflineNotice from "@/components/OfflineNotice";
import { Colors } from "@/constants/Colors";
import { BottomSheetProvider } from "@/contexts/BottomSheetContext";
import { useFonts } from "expo-font";
import {Stack, useRouter, useSegments } from "expo-router";
import { useEffect } from "react";
import { ActivityIndicator, View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import  * as SplashScreen from 'expo-splash-screen';
SplashScreen.preventAutoHideAsync();

const InitialLayout = () => {
  const [loaded, error] = useFonts({
    SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
    Proxima: require("../assets/fonts/Proxima-Nova-Font.otf"),
    SFProBold: require("../assets/fonts/SFPRODISPLAYBOLD.otf"),
    SFProMedium: require("../assets/fonts/SFPRODISPLAYMEDIUM.otf"),
    SFProRegular: require("../assets/fonts/SFPRODISPLAYREGULAR.otf"),
  });

  const { user } = useAuthContext();
  const segments = useSegments();
  const router = useRouter();

  useEffect(() => {
    if (error) throw error;
  }, [error]);
  useEffect(() => {
    if (loaded) {
      SplashScreen.hideAsync();
    }
  }, [loaded]);

  useEffect(() => {
    setTimeout(() => {
      const inAuthGroup = segments[0] === "(app)";
    if (user && !inAuthGroup) {
      router.replace("/(app)/(tabs)/(home)/home");
    } else if (!user) {
      router.replace("/");
    }
    }, 500);
  }, [user]);

  // Conditional rendering based on font loading and user state
  if (!loaded) {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <ActivityIndicator size="large" color={Colors.primary} />
      </View>
    );
  }

  return (
    <Stack>
      <Stack.Screen
        name="index"
        options={{
          presentation:"transparentModal",
          headerShown: false,
        }}
      />
      {/* <Stack.Screen name="login" options={{ headerShown: false }} /> */}
      <Stack.Screen name="sign-up" options={{ headerShown: false }} />
      <Stack.Screen name="verification" options={{ headerShown: false }} />
      <Stack.Screen name="(app)" options={{ headerShown: false }} />
    </Stack>
  );
};

const RootLayoutNav = () => {
  return (
    <AuthProvider>
      <GestureHandlerRootView style={{ flex: 1 }}>
        <OfflineNotice />
        <BottomSheetProvider>
          <InitialLayout />
        </BottomSheetProvider>
      </GestureHandlerRootView>
    </AuthProvider>
  );
};


export default RootLayoutNav;

应用程序表格

import React from "react";
import { StyleSheet } from "react-native";
import {
    Formik
  } from 'formik';

  interface AppFormProps {
    initialValues: any;
    onSubmit: (values: any) => void;
    validationSchema: any;
    children: React.ReactNode;
  }

  const AppForm = ({ initialValues, onSubmit, validationSchema, children }:AppFormProps) => {
    return (
        <Formik
            initialValues={initialValues}
            onSubmit={onSubmit}
            validationSchema={validationSchema}
        >
            {() => <>{children}</>}
        </Formik>
    );
}
export default AppForm;
    System:
      OS: Windows 11 10.0.22631
    Binaries:
      Node: 19.7.0 - C:\Program Files\nodejs\node.EXE
      npm: 9.5.0 - C:\Program Files\nodejs\npm.CMD
    IDEs:
      Android Studio: AI-241.18034.62.2411.12169540       
    npmPackages:
      expo: ~51.0.31 => 51.0.31
      expo-router: ~3.5.23 => 3.5.23
      react: 18.2.0 => 18.2.0
      react-dom: 18.2.0 => 18.2.0
      react-native: 0.74.5 => 0.74.5
      react-native-web: ~0.19.10 => 0.19.12
    Expo Workflow: managed

我已经注释掉了部分代码,并发现错误发生在await函数上。我尝试使用splashscreen.hideasync()手动删除SplashScreen,但仍然面临问题。我尝试使用 apisauce 手动发出请求,而不将数据传递到函数中,只是在函数中简单发送请求,但错误仍然存在。我尝试输入错误的凭据,按钮仅显示活动指示器,然后闪屏再次弹出,并无限地停留在那里,就像我输入正确的凭据时一样。

react-native expo expo-router apisauce expo-splash-screen
1个回答
0
投票

您可以在哪里解决这个问题,因为我目前也遇到同样的事情。

© www.soinside.com 2019 - 2024. All rights reserved.