You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Formik+Yup验证邮箱唯一性时请求URL错误的解决方法

问题描述

尝试用Formik结合Yup实现邮箱唯一性校验(NestJS后端运行在8000端口,React前端运行在3000端口),编写的校验规则代码如下:

const validationSchema = Yup.object().shape({
  username: Yup.string()
    .min(2, 'votre surnom doit contenir minimum 2 caractères')
    .max(30, '30 caractères maximum autorisés')
    .required('Veuillez renseigner un pseudo'),
  email: Yup.string()
    .email('Veuillez renseigner une adresse mail valide')
    .required('Ce champs est obligatoire.')
    .test(
      'email check',
      'email déjà utiliser',
      async (value) =>
        await fetch('http:localhost:8000/users/check_email', {
          method: 'POST',
          headers: {
            'Content-type': 'application/json'
          },
          body: JSON.stringify({ email: value })
        }).then((res) => res.json())
    ),
});

测试时控制台出现错误:

POST http://localhost:3000/localhost:8000/users/check_email 404 (Not Found)

解决方案

1. 修正Fetch URL的语法错误

你的fetch地址少了一个斜杠,http:localhost应该改成http://localhost。缺少斜杠会导致浏览器把这个路径解析为相对当前域名的路径,也就是把前端域名http://localhost:3000和错误路径拼接,最终变成http://localhost:3000/localhost:8000/users/check_email,自然返回404。

修正后的代码片段:

.test(
  'email check',
  'email déjà utiliser',
  async (value) =>
    await fetch('http://localhost:8000/users/check_email', {
      method: 'POST',
      headers: {
        'Content-type': 'application/json'
      },
      body: JSON.stringify({ email: value })
    }).then((res) => res.json())
)

2. 解决跨域问题

前后端端口不同(3000 vs 8000),属于跨域请求,浏览器会拦截,即使URL正确也可能无法正常请求。有两种解决方式:

方式一:后端NestJS配置CORS

在NestJS的main.ts中启用CORS,允许前端域名的请求:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 允许前端域名跨域请求
  app.enableCors({
    origin: 'http://localhost:3000',
    credentials: true,
  });
  await app.listen(8000);
}
bootstrap();

方式二:前端React配置代理

在React项目的package.json中添加proxy字段,将前端的API请求代理到后端:

{
  "name": "your-react-app",
  "version": "0.1.0",
  "proxy": "http://localhost:8000",
  // ...其他配置
}

配置后,fetch可以直接写相对路径,不用写全域名,避免URL错误和跨域问题:

.fetch('/users/check_email', {
  method: 'POST',
  headers: {
    'Content-type': 'application/json'
  },
  body: JSON.stringify({ email: value })
})

3. 优化Yup校验的逻辑可靠性

确保后端接口返回的是布尔值(true表示邮箱可用,false表示已存在),同时处理请求失败的情况(比如网络错误、后端报错),避免校验逻辑异常:

.test(
  'email check',
  'email déjà utiliser',
  async (value) => {
    if (!value) return true; // 空值的情况已经由required校验处理
    try {
      const res = await fetch('http://localhost:8000/users/check_email', {
        method: 'POST',
        headers: {
          'Content-type': 'application/json'
        },
        body: JSON.stringify({ email: value })
      });
      // 先判断响应状态是否成功
      if (!res.ok) return false;
      const isAvailable = await res.json();
      return isAvailable; // 假设后端返回true表示可用,false表示已存在
    } catch (err) {
      // 请求失败时返回false,或者根据需求处理
      console.error('邮箱校验请求失败:', err);
      return false;
    }
  }
)

内容的提问来源于stack exchange,提问作者Ganzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:45:35