「7」next-shopping:登录注册页完善、弹窗改动

我们先来看看当前存在的问题:

  1. 登录注册页面成功后只清空了表单,并没有跳转
  2. 登录注册的提示太小了,能不能换一个大一点的

换一个大一点的状态提示

我们希望换一个大一点的提示,目前用的是react-hot-toast,现在需要换成SweetAlert2 + React example 可以点进去看看效果,很不错,下面我们开始:

安装依赖:

shell 复制代码
pnpm i sweetalert2 sweetalert2-react-content

新建utils/alert.js

js 复制代码
import Swal from 'sweetalert2'
import withReactContent from 'sweetalert2-react-content'

const MySwal = withReactContent(Swal)

const alert = (icon, msg) =>
  MySwal.fire({
    position: 'center',
    icon,
    title: msg,
    showConfirmButton: false,
    timer: 2000,
  })

export const confirmAlert = ({ title, text, icon, confirmButtonText }) =>
  Swal.fire({
    title,
    text,
    icon,
    showCancelButton: false,
    confirmButtonColor: '#3085d6',
    confirmButtonText,
  })

export default alert

可以看到我们定义了默认提示确认框

然后我们在app/(main)/(empty-layout)/register/page.js里面引入,替换掉toast并且,引入router在我们成功注册的时候跳转到首页

js 复制代码
'use client'

import Image from 'next/image'
import Link from 'next/link'
import * as z from 'zod'
import { toast } from 'react-hot-toast'
import { useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { useDispatch } from 'react-redux'
import { useRouter } from 'next/navigation'

import { usePostDataMutation } from '@/store/slices/fetchApiSlice'
import { userLogin } from '@/store/slices/authSlice'
import { DisplayError, Loading } from '@/components'
import alert, { confirmAlert } from '@/utils/alert'

const schema = z
  .object({
    name: z
      .string({
        required_error: '用户名必填',
      })
      .min(3, { message: '用户名最少三个字符' }),
    email: z
      .string({
        required_error: '电子邮件地址必填',
      })
      .email('输入的电子邮件地址无效'),
    password: z
      .string({
        required_error: '密码必填',
      })
      .min(6, { message: '密码必须大于6个字符' }),
    confirmPassword: z
      .string({
        required_error: '确认密码必填',
      })
      .min(6, { message: '密码必须大于6个字符' }),
  })
  .refine(data => data.password === data.confirmPassword, {
    message: '确认密码必须与密码一致',
    path: ['confirmPassword'],
  })

export default function RegisterPage() {
  const dispatch = useDispatch()
  const router = useRouter()

  const [postData, { data, isSuccess, isError, isLoading, error }] = usePostDataMutation()

  const {
    register,
    handleSubmit,
    formState: { errors: formErrors },
    reset,
  } = useForm({
    resolver: zodResolver(schema),
  })

  useEffect(() => {
    if (isSuccess) {
      //      toast.success('注册成功')
      alert('success', data.msg)
      dispatch(userLogin(data.data))
      reset()
      router.push('/')
    }
    if (isError) {
      confirmAlert({
        title: '您的注册有问题',
        text: error?.data?.err,
        icon: 'warning',
        confirmButtonText: '去登录',
      }).then(result => {
        if (result.isConfirmed) router.push('/login')
      })
      //      toast.error(error?.data?.err)
    }
  }, [isSuccess, isError])

  const submitHandler = async ({ name, email, password, confirmPassword }) => {
    if (name && email && password && confirmPassword) {
      postData({ url: '/api/auth/register', body: { name, email, password }, token: '' })
    }
  }

  return (
    <div className=" grid items-center min-h-screen ">
      <div className="container max-w-xl px-12 py-6 space-y-6 lg:border lg:border-gray-100 lg:rounded-lg lg:shadow">
        <div className="relative w-44 h-24 mx-auto">
          <Link passHref href="/">
            <Image src="/images/logo.svg" layout="fill" alt="logo" />
          </Link>
        </div>
        <h2>需要注册</h2>
        <form className="space-y-5" onSubmit={handleSubmit(submitHandler)}>
          <div>
            <input
              type="text"
              className="input"
              name="name"
              placeholder="名称"
              {...register('name')}
            />
            <DisplayError errors={formErrors.name} />
          </div>
          <div>
            <input
              className="input"
              type="text"
              placeholder="电子邮件地址"
              {...register('email')}
            />
            <DisplayError errors={formErrors.email} />
          </div>

          <div>
            <input className="input" type="password" placeholder="密码" {...register('password')} />
            <DisplayError errors={formErrors.password} />
          </div>

          <div>
            <input
              className="input"
              type="password"
              placeholder="重复密码"
              {...register('confirmPassword')}
            />
            <DisplayError errors={formErrors.confirmPassword} />
          </div>

          <button className="btn mx-auto w-60" type="submit" disabled={isLoading}>
            {isLoading ? <Loading /> : '注册'}
          </button>
        </form>

        <div>
          <p className="inline ml-2">已经拥有账户</p>
          <Link href="/login">
            <span className="text-blue-400 text-lg ">登录</span>
          </Link>
        </div>
      </div>
    </div>
  )
}

效果如下:

同理我们把登录页面也改造一下:app/(main)/(empty-layout)/login/page.js

js 复制代码
'use client'

import { useEffect } from 'react'
import Link from 'next/link'
import Image from 'next/image'
import * as z from 'zod'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { toast } from 'react-hot-toast'
import { useDispatch } from 'react-redux'
import { useRouter } from 'next/navigation'

import { usePostDataMutation } from '@/store/slices/fetchApiSlice'
import { DisplayError, Loading } from '@/components'
import { userLogin } from '@/store/slices/authSlice'
import alert, { confirmAlert } from '@/utils/alert'

const schema = z.object({
  email: z
    .string({
      required_error: '邮件地址必填',
    })
    .email('输入的电子邮件地址无效'),
  password: z
    .string({
      required_error: '密码必填',
    })
    .min(6, { message: '密码最少6个字符' }),
})

export default function LoginPage() {
  const dispatch = useDispatch()
  const router = useRouter()

  const [postData, { data, isSuccess, isError, isLoading, error }] = usePostDataMutation()

  const {
    handleSubmit,
    register,
    formState: { errors: formErrors },
    reset,
  } = useForm({
    resolver: zodResolver(schema),
  })

  useEffect(() => {
    if (isSuccess) {
      //      toast.success(data.msg)
      alert('success', data.msg)
      dispatch(userLogin(data.data))
      reset()
      router.push('/')
    }
    if (isError) {
      //      toast.error(error?.data.err)
      confirmAlert({
        title: '您的登录有问题',
        text: error?.data?.err,
        icon: 'warning',
        confirmButtonText: '去注册',
      }).then(result => {
        if (result.isConfirmed) router.push('/register')
      })
    }
  }, [isSuccess, isError])

  const submitHandler = async ({ email, password }) => {
    if (email && password) {
      await postData({
        url: '/api/auth/login',
        body: { email, password },
        token: '',
      })
    }
  }

  return (
    <div className="grid items-center min-h-screen ">
      <div className="container max-w-xl px-12 py-6 space-y-6 lg:border lg:border-gray-100 lg:rounded-lg lg:shadow">
        <div className="relative w-44 h-24 mx-auto">
          <Link passHref href="/">
            <Image src="/images/logo.svg" layout="fill" alt="logo" />
          </Link>
        </div>
        <h2>登录</h2>
        <form className="space-y-5" onSubmit={handleSubmit(submitHandler)}>
          <div>
            <input
              className="input"
              type="text"
              placeholder="电子邮件地址"
              {...register('email')}
            />
            <DisplayError errors={formErrors.email} />
          </div>

          <div>
            <input className="input" type="password" placeholder="密码" {...register('password')} />
            <DisplayError errors={formErrors.password} />
          </div>

          <button className="btn mx-auto w-60" type="submit" disabled={isLoading}>
            {isLoading ? <Loading /> : '登录'}
          </button>
        </form>

        <div>
          <p className="inline ml-2">你还没有注册</p>
          <Link href="/register">
            <span className="text-blue-400 text-lg ">注册</span>
          </Link>
        </div>
      </div>
    </div>
  )
}

效果如下:

今天周五,就少更点,下周见!!

代码地址:feat: 登录提示toast改为alert · liyunfu1998/next-shopping@ba69b5a (github.com)

相关推荐
Yanni4Night几秒前
使用URLPattern API构建自己的路由器 🛣️
前端·javascript
web守墓人7 分钟前
【前端】garn:使用go实现一款类似yarn的依赖管理器
前端
ZePingPingZe8 分钟前
MySQL-InnoDB锁与事务
数据库·mysql
全栈陈序员13 分钟前
Vue 实例挂载的过程是怎样的?
前端·javascript·vue.js·学习·前端框架
韩立学长20 分钟前
Springboot森林资源检测管理系统xowdi7nq(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
h79971021 分钟前
高效统计mysql数据踩坑笔记
数据库·mysql
爱可生开源社区24 分钟前
在数据库迁移中,如何让 AI 真正“可用、可信、可落地”?
数据库·sql·llm
猿小喵25 分钟前
TDSQL-MySQL相对MySQL5.7版本主从复制性能优化
数据库·mysql·性能优化
姓蔡小朋友29 分钟前
MySQL读写锁(元数据锁、意向锁、行锁、间隙锁、临键锁)
数据库·mysql
山峰哥31 分钟前
SQL性能优化实战:从索引策略到查询优化案例全解析
大数据·数据库·sql·oracle·性能优化·架构