第十九章 注册自动登录优化体验

231 阅读2分钟

一、切换注册与登录组件优化

当用户没有登录时访问受保护页面会重定向到http://localhost:3000/login?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2Fdashboard,这时切换到注册时直接跳转到/register ,然后切换回登录页时callbackUrl丢失,所以把NavigationPrompt转为客户端组件,在切换注册和登录页时如果本身存在callbackUrl就需要继续在url里使用,并且需要对URL进行编码。

// src/components/NavigationPrompt.tsx
'use client'
import Link from 'next/link'
import { useSearchParams } from 'next/navigation'

const NavigationPrompt = ({
  isLoginToRegister,
}: {
  isLoginToRegister?: boolean
}) => {
  const searchParams = useSearchParams()
  const callbackUrl = searchParams.get('callbackUrl')
  return (
    <div className="p-6 pt-0 text-center text-sm">
      {isLoginToRegister ? (
        <>
          <span className="text-zinc-600">还没有账号?</span>
          <Link
            href={
              callbackUrl
                ? `/register?callbackUrl=${encodeURIComponent(callbackUrl)}`
                : '/register'
            }
            className="text-primary"
          >
            去注册
          </Link>
        </>
      ) : (
        <>
          <span className="text-zinc-600">已经有账号了?</span>
          <Link
            href={
              callbackUrl
                ? `/login?callbackUrl=${encodeURIComponent(callbackUrl)}`
                : '/login'
            }
            className="text-primary"
          >
            去登录
          </Link>
        </>
      )}
    </div>
  )
}

export default NavigationPrompt

修复样式:

在设计文件展示卡片时修改destructive样式影响了Form表单的错误提示,复原然后单独设置卡片样式,或使用统一的颜色。

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 20% 98%;

二、账号注册自动登录

用户注册完成后执行登录的方法如下

// src/app/(page)/(blockAccessAfterLogin)/register/EmailRegister.tsx
const searchParams = useSearchParams()
const callbackUrl = searchParams.get('callbackUrl')
const pwdRef = useRef('')
const [logging, setLogging] = useState<boolean>(false) // 开始登录
const autoLogin = useCallback(
  async (email: string) => {
    setLogging(true)
    try {
      const response = await signIn('credentials', {
        email,
        password,
        loginType: 'email',
        phoneCode: '',
        redirect: false,
      })
      if (!response?.error) {
        router.push(callbackUrl || '/')
        router.refresh()
        toast({
          title: getMessages('10030'),
          description: getMessages('10034'),
          variant: 'default',
        })
      } else {
        toast({
          title: getMessages('10030'),
          description: getMessages(response.error as TipsCode),
          variant: 'destructive',
        })
      }
      setLogging(false)
    } catch (error) {
      setLogging(false)
      console.log(error)
    }
  },
  [callbackUrl, password, router, toast]
)

注意不要忘记给注册按钮补全加载状态

<Button
  className="w-full"
  type="submit"
  disabled={emailRegisterLoading || logging}
>
  {(emailRegisterLoading || logging) && (
    <Loader2 className="mr-4 h-4 w-4 animate-spin text-white" />
  )}
  注册
</Button>

三、手机号注册自动登录

手机号注册完成后执行登录的方法

// src/app/(page)/(blockAccessAfterLogin)/register/PhoneRegister.tsx
const searchParams = useSearchParams()
const callbackUrl = searchParams.get('callbackUrl')
const [logging, setLogging] = useState<boolean>(false) // 开始登录
const autoLogin = useCallback(async () => {
  setLogging(true)
  try {
    const response = await signIn('credentials', {
      loginType: 'phone',
      phone,
      phoneCode,
      redirect: false,
    })
    if (!response?.error) {
      router.push(callbackUrl || '/')
      router.refresh()
      toast({
        title: getMessages('10030'),
        description: getMessages('10034'),
        variant: 'default',
      })
    } else {
      toast({
        title: getMessages('10030'),
        description: getMessages(response.error as TipsCode),
        variant: 'destructive',
      })
    }
  } catch (error) {
    console.log(error)
  }
  setLogging(false)
}, [callbackUrl, phone, phoneCode, router, toast])

注意不要忘记给注册按钮补全加载状态

<Button
  className="w-full"
  type="submit"
  disabled={phoneRegisterLoading || logging}
>
  {(phoneRegisterLoading || logging) && (
    <Loader2 className="mr-4 h-4 w-4 animate-spin text-white" />
  )}
  注册
</Button>