import { ReactNode, createContext, useEffect, useState } from 'react'; import { useContext } from 'react'; import { router, useSegments } from 'expo-router'; import * as SecureStore from 'expo-secure-store'; import { User } from '../types/user'; import { authenticationService } from '../service/authService'; import {apiClient} from '../service/requets' type AuthProvider = { user: User | null; login: (username: string, password: string, isBinding: boolean) => Promise; logout: () => void; setUser: React.Dispatch>; }; function useProtectedRoute(user: User | null) { const segments = useSegments(); // 添加状态跟踪根布局是否已挂载 const [isLayoutMounted, setIsLayoutMounted] = useState(false); const isUserEmpty = (user: User | null): boolean => { return !user || Object.values(user).every((value) => value === undefined); }; useEffect(() => { // 标记根布局已挂载 setIsLayoutMounted(true); }, []); useEffect(() => { // 等待根布局挂载完成且路由段准备好 if (!isLayoutMounted || !segments.length) return; const inAuthGroup = segments[0] === '(auth)'; const inPublicGroup = segments[0] === '(public)'; if (isUserEmpty(user) && !inPublicGroup) { router.replace('/login'); } else if (!isUserEmpty(user) && inPublicGroup) { router.replace('/(auth)/(tabs)/(home)/mainPage'); } }, [user, segments, isLayoutMounted]); // 添加 isLayoutMounted 依赖 } export const AuthContext = createContext({ user: null, login: async () => false, logout: () => {}, setUser: () => {} }); export function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within a '); } return context; } export default function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); useEffect(() => { const checkToken = async () => { const token = await SecureStore.getItemAsync('accessToken'); if (token) { const userInfo = await getUserFromAccessToken(); if (userInfo) { setUser(userInfo); } } }; checkToken(); }, []); const login = async (username: string, password: string, isBinding: boolean) => { try { const result = await authenticationService.phoneLogin(username, password, isBinding); if (result) { const token = await SecureStore.getItemAsync('accessToken'); if (token) { const userInfo = await getUserFromAccessToken(); if (userInfo) { setUser(userInfo); return true } } return true; } else { return false; } } catch (error) { return false; } }; const getUserFromAccessToken = async () => { try { const res = await apiClient.instance.get(`/clients/customer`); const items = { address: res.data.address, birthday: res.data.birthday, gender: res.data.gender, email: res.data.email, nickname: res.data.nickname, phone: res.data.phone, car: res.data?.defaultCar?.license_plate }; return items; } catch (error) { console.error('GetUser Error:', error); } }; const logout = async () => { try { await authenticationService.logout(); await SecureStore.deleteItemAsync('accessToken'); setUser(null); router.replace('/login'); } catch (error) { console.log('error during logout', error); } }; // console.log('user', user); useProtectedRoute(user); return {children}; }