From 250355562fd23c73cf6f8cfa9d29a9674676877c Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Mon, 15 Jun 2026 22:38:11 +0700 Subject: [PATCH] fix(login): replace useSearchParams with native URLSearchParams + loading spinner - useSearchParams can lose params during re-renders, causing blank page - Use native window.location.search + URLSearchParams instead (always accessible) - Add oauthProcessing spinner state so user sees 'Menyelesaikan login...' instead of blank page while /auth/me is being called Co-Authored-By: Claude --- apps/web/src/pages/login-page.tsx | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/apps/web/src/pages/login-page.tsx b/apps/web/src/pages/login-page.tsx index 954dd11..81594fa 100644 --- a/apps/web/src/pages/login-page.tsx +++ b/apps/web/src/pages/login-page.tsx @@ -1,23 +1,28 @@ import { useState, useEffect, useRef } from "react"; -import { Link, useNavigate, useSearchParams } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { AuthForm } from "@/components/auth-form"; import { apiClient, setAuthToken } from "@/lib/api-client"; import { useAuthStore } from "@/store/auth-store"; +function getUrlParam(name: string): string | null { + return new URLSearchParams(window.location.search).get(name); +} + export function LoginPage() { const navigate = useNavigate(); const queryClient = useQueryClient(); const setUser = useAuthStore((state) => state.setUser); const [error, setError] = useState(null); - const [searchParams] = useSearchParams(); const oauthTokenConsumed = useRef(false); + const [oauthProcessing, setOauthProcessing] = useState(false); // Handle OAuth callback: the API redirects to /login?token= useEffect(() => { - const token = searchParams.get("token"); + const token = getUrlParam("token"); if (!token || oauthTokenConsumed.current) return; oauthTokenConsumed.current = true; + setOauthProcessing(true); // Store token for future API calls and fetch user setAuthToken(token); @@ -31,12 +36,13 @@ export function LoginPage() { }) .catch((err) => { setAuthToken(null); + setOauthProcessing(false); setError(err instanceof Error ? err.message : "Google login gagal"); }); - }, [searchParams, setUser, queryClient, navigate]); + }, [setUser, queryClient, navigate]); // Show OAuth error from query param - const oauthError = searchParams.get("error"); + const oauthError = getUrlParam("error"); const meQuery = useQuery({ queryKey: ["auth", "me"], queryFn: () => apiClient.getMe(), @@ -53,6 +59,18 @@ export function LoginPage() { setError(err instanceof Error ? err.message : "Login gagal"), }); + // Show loading spinner while OAuth token is being processed + if (oauthProcessing) { + return ( +
+
+
+

Menyelesaikan login dengan Google...

+
+
+ ); + } + return (