SimpleAuth
ReactComponents

VerifyEmailCallback

Landing page component that verifies the email token on load.

Overview

VerifyEmailCallback mounts useVerifyEmail with the token from your verification link and verifies it on load. Use it on the route your verification emails point to (for example /verify-email?token=…).

Preview

Interactive preview requires JavaScript.

Install

npx @simpleauthjs/react add verify-email --style minimal

The install snippet uses --style minimal. You can also use --style modern. Style variants compares those two in the live preview. Run npx @simpleauthjs/react add --help for every --style slug the CLI accepts.

Requires add sign-up first.

Props

NameTypeRequiredDescription
tokenstringYesToken from your verification URL.
onSuccess() => voidNoCalled when verification succeeds.

Usage

"use client"

import { VerifyEmailCallback } from "@/components/simpleauth"
import { useRouter } from "next/navigation"

export function VerifyEmailClient({ token }: { token: string }) {
  const router = useRouter()

  return <VerifyEmailCallback token={token} onSuccess={() => router.replace("/login")} />
}
// app/verify-email/page.tsx
import { VerifyEmailClient } from "./verify-email-client"

export default function Page({ searchParams }: { searchParams: { token?: string } }) {
  const token = searchParams.token ?? ""
  if (!token) {
    return <p>Invalid or missing verification link.</p>
  }
  return <VerifyEmailClient token={token} />
}

Source

components/simpleauth/hooks/use-verify-email.ts
"use client"

import { useCallback, useEffect, useRef, useState } from "react"
import { SimpleAuthError, type SuccessResponse } from "@simpleauthjs/core"
import { useSimpleAuthClient } from "../provider"

function getErrorMessage(error: unknown) {
  if (error instanceof SimpleAuthError) {
    return error.message
  }

  if (error instanceof Error) {
    return error.message
  }

  return "Unable to verify email."
}

type UseVerifyEmailOptions = {
  token?: string
}

export function useVerifyEmail(options: UseVerifyEmailOptions = {}) {
  const { token: initialToken } = options
  const auth = useSimpleAuthClient()
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [data, setData] = useState<SuccessResponse | null>(null)
  const autoRunRef = useRef(false)

  const verify = useCallback(
    async (token: string) => {
      setIsLoading(true)
      setError(null)

      try {
        const response = await auth.verifyEmail({ token })
        setData(response)
        return response
      } catch (requestError) {
        setData(null)
        setError(getErrorMessage(requestError))
        throw requestError
      } finally {
        setIsLoading(false)
      }
    },
    [auth],
  )

  useEffect(() => {
    if (!initialToken || autoRunRef.current) {
      return
    }

    autoRunRef.current = true
    verify(initialToken).catch(() => {})
  }, [initialToken, verify])

  function reset() {
    autoRunRef.current = false
    setData(null)
    setError(null)
    setIsLoading(false)
  }

  return {
    verify,
    data,
    error,
    isError: Boolean(error),
    isLoading,
    isSuccess: Boolean(data?.success),
    reset,
  }
}

Customisation

Owned by you

Files live at components/simpleauth/ui/verify-email-callback.tsx and components/simpleauth/styles/verify-email-callback.css.

On this page