useSignUp() and useSignIn()
Overview
If our Prebuilt Components don't meet your needs, you can build a fully custom sign-up or sign-in flow using the React hooks useSignUp()
and useSignIn()
respectively.
useSignUp()
The useSignUp()
hook gives you access to the SignUp
object and its available methods in order to build a custom sign-up flow. The SignUp
object will also contain the state of the sign-up attempt that is currently in progress, which gives you the ability to examine all the details and act accordingly.
Usage
Getting access to the SignUp
object from inside one of your components is easy. Note that the useSignUp()
hook can only be used inside a <ClerkProvider/> context.
The following example accesses the SignUp
object to check the current sign-up attempt's status.
1import { useSignUp } from '@clerk/nextjs';23export default function SignUpStep() {4const { isLoaded, signUp } = useSignUp();56if (!isLoaded) {7// Handle loading state8return null;9}1011return (12<div>13The current sign up attempt status14is {signUp.status}.15</div>16);17}
In a more involved example, we show an approach to create a custom form for registering users, in this case with a Password strategy. This assumes that you don't have any additional requirements like username or phone enabled
1import { useState } from "react";2import { useSignUp } from "@clerk/nextjs";3import { useRouter } from "next/router";45export default function SignUpForm() {6const { isLoaded, signUp, setActive } = useSignUp();7const [emailAddress, setEmailAddress] = useState("");8const [password, setPassword] = useState("");9const [pendingVerification, setPendingVerification] = useState(false);10const [code, setCode] = useState("");11const router = useRouter();12// start the sign up process.13const handleSubmit = async (e) => {14e.preventDefault();15if (!isLoaded) {16return;17}1819try {20await signUp.create({21emailAddress,22password,23});2425// send the email.26await signUp.prepareEmailAddressVerification({ strategy: "email_code" });2728// change the UI to our pending section.29setPendingVerification(true);30} catch (err: any) {31console.error(JSON.stringify(err, null, 2));32}33};3435// This verifies the user using email code that is delivered.36const onPressVerify = async (e) => {37e.preventDefault();38if (!isLoaded) {39return;40}4142try {43const completeSignUp = await signUp.attemptEmailAddressVerification({44code,45});46if (completeSignUp.status !== "complete") {47/* investigate the response, to see if there was an error48or if the user needs to complete more steps.*/49console.log(JSON.stringify(completeSignUp, null, 2));50}51if (completeSignUp.status === "complete") {52await setActive({ session: completeSignUp.createdSessionId })53router.push("/");54}55} catch (err: any) {56console.error(JSON.stringify(err, null, 2));57}58};5960return (61<div>62{!pendingVerification && (63<form>64<div>65<label htmlFor="email">Email</label>66<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />67</div>68<div>69<label htmlFor="password">Password</label>70<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />71</div>72<button onClick={handleSubmit}>Sign up</button>73</form>74)}75{pendingVerification && (76<div>77<form>78<input79value={code}80placeholder="Code..."81onChange={(e) => setCode(e.target.value)}82/>83<button onClick={onPressVerify}>84Verify Email85</button>86</form>87</div>88)}89</div>90);91}
useSignIn()
The useSignIn()
hook gives you access to the SignIn
object and its available methods in order to build a custom sign-in flow. The SignIn
object will also contain the state of the sign-in attempt that is currently in progress, which gives you the ability to example all the details and act accordingly.
Usage
Getting access to the SignIn
object from inside one of your components is easy. Note that the useSignIn()
hook can only be used inside a <ClerkProvider/> context.
The following example accesses the SignIn
object to check the current sign-in attempt's status.
import { useSignIn } from '@clerk/nextjs';export default function SignInStep() {const { isLoaded, signIn } = useSignIn();if (!isLoaded) {// Handle loading statereturn null;}return (<div>The current sign in attempt statusis {signIn.status}.</div>);}
In a more involved example, we show an approach to create a custom form for signing in users, in this case with a Password strategy.
1import { useState } from "react";2import { useSignIn } from "@clerk/nextjs";3import { useRouter } from "next/router";45export default function SignInForm() {6const { isLoaded, signIn, setActive } = useSignIn();7const [emailAddress, setEmailAddress] = useState("");8const [password, setPassword] = useState("");9const router = useRouter();10// start the sign In process.11const handleSubmit = async (e) => {12e.preventDefault();13if (!isLoaded) {14return;15}1617try {18const result = await signIn.create({19identifier: emailAddress,20password,21});2223if (result.status === "complete") {24console.log(result);25await setActive({ session: result.createdSessionId });26router.push("/")27}28else {29/*Investigate why the login hasn't completed */30console.log(result);31}3233} catch (err: any) {34console.error("error", err.errors[0].longMessage)35}36};3738return (39<div>40<form>41<div>42<label htmlFor="email">Email</label>43<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />44</div>45<div>46<label htmlFor="password">Password</label>47<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />48</div>49<button onClick={handleSubmit}>Sign In</button>50</form>51</div>52);53}