import { useEffect, useState, useRef } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { useAuth } from '../context/useAuth'; import { ssafyCallback } from '../api/auth'; // Inline styles are intentional for this simple callback/loading page — not worth a separate CSS file. export default function SSAFYCallbackPage() { const [error, setError] = useState(''); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const { setUserFromSSAFY } = useAuth(); // useRef(false) prevents double-execution in React 18+ StrictMode, // which remounts components in development. The ref persists across // the StrictMode remount, ensuring the OAuth callback runs only once. const called = useRef(false); useEffect(() => { if (called.current) return; called.current = true; const code = searchParams.get('code'); if (!code) { setError('인가 코드가 없습니다.'); // eslint-disable-line react-hooks/set-state-in-effect -- error state from URL param check return; } ssafyCallback(code) .then((data) => { setUserFromSSAFY(data); navigate('/', { replace: true }); }) .catch((err) => { setError(err.message || 'SSAFY 로그인에 실패했습니다.'); }); }, [searchParams, setUserFromSSAFY, navigate]); if (error) { return (

{error}

); } return (

SSAFY 로그인 처리 중...

); }