🚀 用 Vite + React + Ky 联调后端:一个完整表单异常处理指南
场景 :
前端使用 Vite 构建,通过 Ky 发送请求:后端后端跑在
172.**.*.**:*****/serve
。需求:
- 把用户填写的邮箱、姓名保存到后端;
- 网络异常 、业务异常 、超时 都要优雅提示;
- 代码结构清晰,方便日后复用。
1. 项目骨架速览
文件 | 职责 |
---|---|
vite.config.ts |
代理 /api → http://172.**.*.**:*****/serve |
src/api/index.ts |
用 Ky 封装通用 request 实例 |
WaitlistForm.tsx |
React 表单组件,负责校验 + 提交 + 异常处理 |
2. Vite 代理配置
ts
// vite.config.ts
server: {
proxy: {
"/api": {
target: "http://172.**.*.**:*****/serve",
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ""),
},
},
}
- 本地
fetch('后端接口路径')
会被 Vite 转发到真实后端,无 CORS 烦恼。 - 上线时把
/api
指向真正的域名即可,零改动。
3. 用 Ky 封装请求
ts
// src/api/index.ts
import ky from 'ky';
const request = ky.create({
prefixUrl: '/api', // 自动拼接
timeout: 600_000, // 10 min,可按需调整
});
export async function form(data: any) {
return request.post('后端接口路径', data);
}
prefixUrl
让后续路径保持简洁。- Ky 自带 timeout / retry / 错误处理 中间件,比原生 fetch 更顺手。
4. React 表单核心逻辑
4.1 状态设计
ts
const [formData, setFormData] = useState({
email: "",
firstName: "",
lastName: "",
});
const [submitted, setSubmitted] = useState(false);
const [error, setError] = useState("");
4.2 前端校验
- 必填字段、邮箱格式、长度 ≤ 50 字符。
- 早失败:前端先挡一波,减少无效请求。
ts
if (!isValidEmail(formData.email)) {
setError("Please enter a valid email address.");
return;
}
4.3 提交 & 异常处理
ts
try {
// 1️⃣ 发送
const response = await form({
json: {
email: formData.email,
firstName: formData.firstName,
lastName: formData.lastName,
},
});
// 2️⃣ 网络层检查(HTTP 状态码)
if (!response.ok) {
throw new Error("Network error. Please check your connection.");
}
// 3️⃣ 业务层检查(后端返回 success=false)
const data: { success?: boolean; msg?: string } = await response.json();
if (data?.success === false) {
throw new Error(data.msg || "Submission failed. Please try again later.");
}
// 4️⃣ 成功
setSubmitted(true);
setFormData({ email: "", firstName: "", lastName: "" });
} catch (error: any) {
// 5️⃣ 统一收口
setError(error?.message || "Submission failed. Please try again later.");
}
异常分层
类型 | 触发示例 | 最终提示 |
---|---|---|
网络错误 | 断网、502 | "Network error. Please check your connection." |
业务错误 | {success:false, msg:"邮箱已存在"} |
"邮箱已存在" |
超时 | Ky 自带 | "Submission failed... (或配置 Ky timeout 提示) |
JSON 解析 | 后端返回 HTML | 同上兜底 |
5. 小技巧 & 踩坑
-
后端返回非 JSON
在 catch 内统一
error.message
兜底即可,用户不会看到晦涩的Unexpected token <
。 -
代理只在 dev 生效
打包后把
/api
指向生产域名,或使用环境变量切换。 -
调试代理
vite --debug
或浏览器 Network 面板观察实际转发路径。
6. 总结
- Vite 代理 解决本地跨域。
- Ky 比 fetch 更友好,自带 timeout、retry。
- 异常分层 :HTTP → 业务 → 兜底,全部收敛到
catch
,前端提示清晰。 - 零配置切换:dev 用代理,prod 用真实域名,一行代码都不用改。
把这段逻辑沉淀为 hooks 或 封装函数,以后任何表单都能直接复用。Happy coding!