Fix bug in auth provider
This commit is contained in:
@ -1,5 +1,4 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, {
|
import React, {
|
||||||
type ReactNode,
|
type ReactNode,
|
||||||
createContext,
|
createContext,
|
||||||
@ -44,15 +43,18 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
const [avatarUrl, setAvatarUrl] = useState<string | null>(null);
|
const [avatarUrl, setAvatarUrl] = useState<string | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isInitialized, setIsInitialized] = useState(false);
|
const [isInitialized, setIsInitialized] = useState(false);
|
||||||
|
|
||||||
const fetchingRef = useRef(false);
|
const fetchingRef = useRef(false);
|
||||||
|
|
||||||
const fetchUserData = useCallback(async () => {
|
const fetchUserData = useCallback(async (showLoading = true) => {
|
||||||
if (fetchingRef.current) return;
|
if (fetchingRef.current) return;
|
||||||
fetchingRef.current = true;
|
fetchingRef.current = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
// Only show loading for initial load or manual refresh
|
||||||
|
if (showLoading) {
|
||||||
|
setIsLoading(true);
|
||||||
|
}
|
||||||
|
|
||||||
const userResponse = await getUser();
|
const userResponse = await getUser();
|
||||||
const profileResponse = await getProfile();
|
const profileResponse = await getProfile();
|
||||||
|
|
||||||
@ -62,6 +64,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
setAvatarUrl(null);
|
setAvatarUrl(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setUser(userResponse.data);
|
setUser(userResponse.data);
|
||||||
setProfile(profileResponse.data);
|
setProfile(profileResponse.data);
|
||||||
|
|
||||||
@ -71,12 +74,14 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
bucket: 'avatars',
|
bucket: 'avatars',
|
||||||
url: profileResponse.data.avatar_url,
|
url: profileResponse.data.avatar_url,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (avatarResponse.success) {
|
if (avatarResponse.success) {
|
||||||
setAvatarUrl(avatarResponse.data);
|
setAvatarUrl(avatarResponse.data);
|
||||||
} else setAvatarUrl(null);
|
} else {
|
||||||
|
setAvatarUrl(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setAvatarUrl(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error(
|
||||||
'Auth fetch error: ',
|
'Auth fetch error: ',
|
||||||
@ -88,7 +93,9 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
toast.error('Failed to load user data!');
|
toast.error('Failed to load user data!');
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
if (showLoading) {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
setIsInitialized(true);
|
setIsInitialized(true);
|
||||||
fetchingRef.current = false;
|
fetchingRef.current = false;
|
||||||
}
|
}
|
||||||
@ -96,24 +103,31 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const supabase = createClient();
|
const supabase = createClient();
|
||||||
|
|
||||||
fetchUserData().catch((error) => {
|
// Initial fetch with loading
|
||||||
|
fetchUserData(true).catch((error) => {
|
||||||
console.error('💥 Initial fetch error:', error);
|
console.error('💥 Initial fetch error:', error);
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: { subscription },
|
data: { subscription },
|
||||||
} = supabase.auth.onAuthStateChange(async (event, session) => {
|
} = supabase.auth.onAuthStateChange(async (event, session) => {
|
||||||
|
console.log('Auth state change:', event); // Debug log
|
||||||
|
|
||||||
if (event === 'SIGNED_IN') {
|
if (event === 'SIGNED_IN') {
|
||||||
await fetchUserData();
|
// Background refresh without loading state
|
||||||
|
await fetchUserData(false);
|
||||||
} else if (event === 'SIGNED_OUT') {
|
} else if (event === 'SIGNED_OUT') {
|
||||||
setUser(null);
|
setUser(null);
|
||||||
setProfile(null);
|
setProfile(null);
|
||||||
setAvatarUrl(null);
|
setAvatarUrl(null);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
} else if (event === 'TOKEN_REFRESHED') {
|
||||||
|
// Silent refresh - don't show loading
|
||||||
|
await fetchUserData(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
};
|
};
|
||||||
@ -129,7 +143,6 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
throw new Error(result.error ?? 'Failed to update profile');
|
throw new Error(result.error ?? 'Failed to update profile');
|
||||||
}
|
}
|
||||||
|
|
||||||
setProfile(result.data);
|
setProfile(result.data);
|
||||||
|
|
||||||
// If avatar was updated, refresh the avatar URL
|
// If avatar was updated, refresh the avatar URL
|
||||||
@ -139,12 +152,10 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
url: result.data.avatar_url,
|
url: result.data.avatar_url,
|
||||||
transform: { width: 128, height: 128 },
|
transform: { width: 128, height: 128 },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (avatarResponse.success) {
|
if (avatarResponse.success) {
|
||||||
setAvatarUrl(avatarResponse.data);
|
setAvatarUrl(avatarResponse.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success('Profile updated successfully!');
|
toast.success('Profile updated successfully!');
|
||||||
return { success: true, data: result.data };
|
return { success: true, data: result.data };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -155,7 +166,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const refreshUserData = useCallback(async () => {
|
const refreshUserData = useCallback(async () => {
|
||||||
await fetchUserData();
|
await fetchUserData(true); // Manual refresh shows loading
|
||||||
}, [fetchUserData]);
|
}, [fetchUserData]);
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
@ -173,7 +184,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
{children}
|
{children}
|
||||||
</AuthContext.Provider>
|
</AuthContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useAuth = () => {
|
export const useAuth = () => {
|
||||||
const context = useContext(AuthContext);
|
const context = useContext(AuthContext);
|
||||||
@ -181,4 +192,4 @@ export const useAuth = () => {
|
|||||||
throw new Error('useAuth must be used within an AuthProvider');
|
throw new Error('useAuth must be used within an AuthProvider');
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
};
|
||||||
|
Reference in New Issue
Block a user