import { useEffect, useRef, useState } from 'react'; import { Link, useSearchParams } from 'react-router-dom'; import Card from 'antd/es/card'; import Typography from 'antd/es/typography'; import Alert from 'antd/es/alert'; import Button from 'antd/es/button'; import Spin from 'antd/es/spin'; import { verifyEmail } from './customerApi'; import { useCustomerAuth } from './CustomerAuthContext'; const { Title, Paragraph } = Typography; type Status = 'verifying' | 'verified' | 'failed'; export default function VerifyEmail() { const [searchParams] = useSearchParams(); const token = searchParams.get('token'); // Derived from the URL rather than discovered in an effect. Whether the link // carries a token is knowable during the first render, so routing it through // an effect made this component render once as a spinner in a state that was // never true — a link with no token was never "verifying". See #99. const [status, setStatus] = useState(token ? 'verifying' : 'failed'); const [error, setError] = useState( token ? null : 'This link is missing its verification token.' ); const { refresh } = useCustomerAuth(); // The backend deletes the token once it succeeds, so a second request for the // same token comes back as "invalid or expired" and would overwrite the success // state with an error. StrictMode runs effects twice in dev, which is exactly // that scenario, so pin the request to a single firing. const requested = useRef(false); useEffect(() => { if (requested.current) return; requested.current = true; // Nothing to do: the missing-token case is already the initial state. if (!token) return; verifyEmail(token) .then(() => { setStatus('verified'); refresh(); }) .catch((err: Error) => { setStatus('failed'); setError(err.message); }); }, [token, refresh]); return (
Email verification {status === 'verifying' && ( Verifying your email address… )} {status === 'verified' && ( <> )} {status === 'failed' && ( <> Verification links expire 24 hours after the account is created. If yours has expired, the link can no longer be used. )}
); }