我使用 JWT 令牌为我的应用程序使用 React 上下文 API 进行持久登录。
当关闭和打开应用程序时,首先加载登录屏幕,然后加载主屏幕,如何解决延迟。从 VS 代码重新加载时也会发生同样的事情。
import { createContext, useContext, useEffect, useState } from "react";
import axios from "axios";
import * as SecureStore from 'expo-secure-store';
import { handleError } from "../utils/helperFunctions";
import { API_URL, AUTH_KEY } from "../constants/strings";
import { setAxiosAuthHeader } from "../utils/configHelpers";
import { AuthProps, ILoginDeatils } from "../interface/AuthInterface";
const AuthContext = createContext<AuthProps>({});
export const useAuth = () => {
return useContext(AuthContext);
}
export const AuthProvider = ({ children }: any) => {
const [authState, setAuthState] = useState<ILoginDeatils>(InitialLoginState);
const [loading, setLoading] = useState<boolean>(false);
useEffect(() => {
setLoading(true);
const loadUserAuthState = async () => {
const loggedInDetails = await SecureStore.getItemAsync(AUTH_KEY);
if (loggedInDetails) {
const loggedInUserDetails:ILoginDeatils = JSON.parse(loggedInDetails);
setAxiosAuthHeader(loggedInUserDetails.token);
setAuthState(loggedInUserDetails);
}
};
loadUserAuthState();
setLoading(false);
}, [])
const login = async (email: string, password: string) => {
const loginInfo = { email, password };
const result = await axios.post(`${API_URL}/auth/login`, loginInfo);
if (!result.data.verified || !result.data.completedProfile) {
return result;
}
const loggedInDetails: ILoginDeatils = {
registerId: result.data.loginDetils.registerId,
gender: result.data.loginDetils.gender,
email: result.data.loginDetils.email,
profileId: result.data.loginDetils.profileId,
name: result.data.loginDetils.name,
phone: result.data.loginDetils.phone,
token: result.data.token,
authenticated: true
}
await SecureStore.setItemAsync(AUTH_KEY, JSON.stringify(loggedInDetails));
setAxiosAuthHeader(loggedInDetails.token);
setAuthState(loggedInDetails)
return result;
}
const logout = async () => {
// Delete token from stroage
await SecureStore.deleteItemAsync(AUTH_KEY);
// Update HTTP Headers
setAxiosAuthHeader("")
// Reset auth state
setAuthState(InitialLoginState);
Promise.resolve(true);
}
const value = {
onRegister: register,
onLogin: login,
onLogout: logout,
authState,
loading,
setAuthState
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
}
App.tsx
import 'react-native-gesture-handler';
import { useFonts } from 'expo-font';
import React, { useEffect } from 'react';
import * as SplashScreen from 'expo-splash-screen';
import { PaperProvider } from 'react-native-paper';
import FlashMessage from "react-native-flash-message";
import { fontsFamily } from './src/styles/fonts';
import { FormsProvider } from './src/context/FormsContext';
import { AuthProvider } from './src/context/AuthContext';
import { ThemeProvider } from './src/theme/ThemeProvider';
import AppNavigation from './src/navigations/AppNavigation';
SplashScreen.preventAutoHideAsync();
export default function App() {
const [fontsLoaded, fontError] = useFonts(fontsFamily);
useEffect(() => {
if (fontsLoaded || fontError) {
SplashScreen.hideAsync();
}
}, [fontsLoaded, fontError]);
if (!fontsLoaded && !fontError) {
return null;
}
return (
<PaperProvider>
<ThemeProvider>
<FormsProvider>
<AuthProvider>
<AppNavigation />
</AuthProvider>
</FormsProvider>
</ThemeProvider>
<FlashMessage />
</PaperProvider>
);
}
AppNavigation.tsx
import React from 'react'
import { useAuth } from '../context/AuthContext';
import ExpoStatusBar from 'expo-status-bar/build/ExpoStatusBar';
import { NavigationContainer } from '@react-navigation/native';
import SideDrawer from './drawer/SideDrawer';
import Auth from './stack/Auth';
import { useAMTheme } from '../theme/ThemeProvider';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import AnimatedSplashScreen from '../components/uiElements/loader/AnimatedSplashScreen';
const AppNavigation = () => {
const { authState, loading } = useAuth();
const { isDark } = useAMTheme();
if(loading){
return <AnimatedSplashScreen/>
}
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<ExpoStatusBar style={isDark ? "light" : "dark"} backgroundColor={'transparent'} />
{
authState?.authenticated ? (
<NavigationContainer>
<SideDrawer />
</NavigationContainer>
) : (
<NavigationContainer>
<Auth />
</NavigationContainer>
)
}
</GestureHandlerRootView>
)
}
export default AppNavigation
请有人帮忙解决这个问题或分享任何 github 项目以供参考
问题视频链接:https://drive.google.com/file/d/1dnM6IIV5jCvzbrJuf1cV3ElVW7segKSZ/view?usp=drive_link
loadUserAuthState
函数异步运行,因此setLoading(false)
将在准备好之前执行。解决此问题的一种方法是在函数内移动加载状态处理。像这样的东西:
useEffect(() => {
const loadUserAuthState = async () => {
setLoading(true);
...
setLoading(false);
};
loadUserAuthState();
}, []);