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
相关产品推荐
相关产品推荐

