Skip to main content

useSignUp()

The useSignUp() hook exposes programmatic access to the underlying registration infrastructure of the Wacht platform. It bypasses the built-in <SignUpForm /> component while enforcing required security validations, cryptographic exchanges, and data integrity checks. This hook is utilized when custom registration logic is required, such as within multi-stage onboarding sequences or environments subject to strict design system compliance.

Hook Import

import { useSignUp } from "@wacht/nextjs";

Architecture

Establishing a secure user identity record requires a phased API interaction sequence. The useSignUp hook mirrors this process through discrete state transitions and API invocations.
loading
boolean
Indicates whether the SDK is actively processing a network request or managing internal state transitions.
signUp
SignUpFunction
signupAttempt
SignupAttempt | null
The active state of the current registration sequence.
discardSignupAttempt
() => void
Terminates and clears the current registration sequence state from memory.

Implementation Guidelines

Orchestrating a Verification Flow

Robust identity configuration mandates verification of the contact identifier supplied during the initial registration phase. The following implementation outlines the process of initializing an account and executing a One-Time Passcode (OTP) verification:
import { useSignUp } from "@wacht/nextjs";
import { useState } from "react";
import { useNavigate } from "@tanstack/react-router";

export function CustomRegistrationForm() {
  const { loading, signUp } = useSignUp();
  const navigate = useNavigate();

  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [pendingVerification, setPendingVerification] = useState(false);
  const [code, setCode] = useState("");

  const handleRegistrationInitialization = async (e: React.FormEvent) => {
    e.preventDefault();
    if (loading) return;

    try {
      await signUp.create({ email, password });
      await signUp.prepareVerification({ strategy: "email_otp" });
      setPendingVerification(true);
    } catch (err: any) {
      console.error("Initialization failed:", err);
    }
  };

  const handleVerificationSubmission = async (e: React.FormEvent) => {
    e.preventDefault();
    if (loading) return;

    try {
      await signUp.completeVerification(code);
      // Backend automatically maps session cookies upon successful verification completion
      navigate({ to: "/dashboard" });
    } catch (err: any) {
      console.error("Verification validation failed:", err);
    }
  };

  if (pendingVerification) {
    return (
      <form onSubmit={handleVerificationSubmission} className="flex flex-col gap-4">
        <input 
          value={code} 
          placeholder="Execution Code..." 
          onChange={(e) => setCode(e.target.value)} 
          className="border p-2 rounded"
        />
        <button type="submit" disabled={loading} className="bg-indigo-600 text-white rounded p-2">
          {loading ? "Verifying..." : "Confirm Verification"}
        </button>
      </form>
    );
  }

  return (
    <form onSubmit={handleRegistrationInitialization} className="flex flex-col gap-4">
      <input 
        type="email" 
        value={email} 
        onChange={(e) => setEmail(e.target.value)} 
        placeholder="Identity Address"
        className="border p-2 rounded"
      />
      <input 
        type="password" 
        value={password} 
        onChange={(e) => setPassword(e.target.value)} 
        placeholder="Secure Credential"
        className="border p-2 rounded"
      />
      <button type="submit" disabled={loading} className="bg-blue-600 text-white rounded p-2">
        {loading ? "Processing..." : "Register Subject"}
      </button>
    </form>
  );
}