如何用Fetch API提交FormData?解决POST请求420错误
修复Fetch API提交表单时的420错误
问题描述
需要提交的表单数据结构:
{ "code": "test1", "article": "door", "price": 12, "vat": null, "status": 1, "company_id": 10 }
点击Add按钮通过Fetch API提交时,控制台出现420错误:
POST https://api.factarni.tn/article/create 420
当前实现代码:
const New = ({ inputs, title }) => { const handleClick = (e) => { e.preventDefault(); fetch("https://api.factarni.tn/article/create", { method: "POST", body: JSON.stringify({ code: "test1", article: "door", price: 12, vat: null, status: 1, company_id: 30, }), headers: { Authorization: "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkMWIxOWYwZjU4ZTJjOWE5Njc3M2M5MmNmODA0NDEwMTc5NzEzMjMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoibW9oYW1lZCIsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9mYWN0YXJuaSIsImF1ZCI6ImZhY3Rhcm5pIiwiYXV0aF90aW1lIjoxNjYwNzIzNDA5LCJ1c2VyX2lkIjoiQ3hKejMwR1ExYlVLMVd0SjdDa1NVUzJ4NW5rMSIsInN1YiI6IkN4SnozMEdRMWJVSzFXdEo3Q2tTVVMyeDVuazEiLCJpYXQiOjE2NjA3MjM0MDksImV4cCI6MTY2MDcyNzAwOSwiZW1haWwiOiJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.XoDs7DEYWQm9AwWFEbR7CtKpgvTh_zH8E5V1e8nUp5OwQT3hjKMUBFRCa7p_v-1TXAF5VoSDGTt0vZRgtPj6u7mIzagi0CPkuQYVyUkhHo2wBOV-IHbCRTqg-M4d6WDQvfSp1C0OzUnEg8eduUr7F7znuLnAUZQKBZ_Xp9ogj8aAZo-R8Na0HE5h0L9fIslD9UFBj2192EVebpb2DJir16beotXpd04d_qC1WCrN3WMsWdvgl2BRrTiG6SkqqwZH1hZzNkajNtIrhpYLnSOBoE3SsiIczvctqexynxmlle7gWaBN22t1M3sk3NHCkdfkSrXRi3PIBr71qw2QWltkyA", }, }).then((response) => response.json()); }; return ( <div className="New"> <Sidebar /> <div className="newContainer"> <Navbar /> <div className="top"> <h1>{title}</h1> </div> <div className="bottom"> <div className="right"> <form> <div className="formInput"></div> {inputs.map((input) => ( <div className="formInput" key={input.id}> <label>{input.label} </label> <input type={input.type} placeholder={input.placeholder} /> </div> ))} <button onClick={handleClick}>Add</button> </form> </div> </div> </div> </div> ); }; export default New;
修复方案
420属于自定义HTTP状态码,通常和请求格式、令牌有效性、限流规则相关,按以下步骤排查修复:
1. 补充Content-Type请求头
API无法识别JSON格式的请求体,需添加Content-Type: application/json头:
headers: { Authorization: "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkMWIxOWYwZjU4ZTJjOWE5Njc3M2M5MmNmODA0NDEwMTc5NzEzMjMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoibW9oYW1lZCIsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9mYWN0YXJuaSIsImF1ZCI6ImZhY3Rhcm5pIiwiYXV0aF90aW1lIjoxNjYwNzIzNDA5LCJ1c2VyX2lkIjoiQ3hKejMwR1ExYlVLMVd0SjdDa1NVUzJ4NW5rMSIsInN1YiI6IkN4SnozMEdRMWJVSzFXdEo3Q2tTVVMyeDVuazEiLCJpYXQiOjE2NjA3MjM0MDksImV4cCI6MTY2MDcyNzAwOSwiZW1haWwiOiJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.XoDs7DEYWQm9AwWFEbR7CtKpgvTh_zH8E5V1e8nUp5OwQT3hjKMUBFRCa7p_v-1TXAF5VoSDGTt0vZRgtPj6u7mIzagi0CPkuQYVyUkhHo2wBOV-IHbCRTqg-M4d6WDQvfSp1C0OzUnEg8eduUr7F7znuLnAUZQKBZ_Xp9ogj8aAZo-R8Na0HE5h0L9fIslD9UFBj2192EVebpb2DJir16beotXpd04d_qC1WCrN3WMsWdvgl2BRrTiG6SkqqwZH1hZzNkajNtIrhpYLnSOBoE3SsiIczvctqexynxmlle7gWaBN22t1M3sk3NHCkdfkSrXRi3PIBr71qw2QWltkyA", "Content-Type": "application/json" }
2. 验证JWT令牌与权限
- 解码JWT令牌,检查
exp字段确认是否过期; - 核对
company_id:你示例表单用的是10,但代码里传的是30,确认该ID是否属于当前用户有权限操作的范围; - 若令牌过期,重新获取有效的Authorization令牌。
3. 检查请求限流
420可能是API触发了频率限制,暂停一段时间后重试,或确认API的调用次数限制规则。
4. 同步表单输入与提交数据
当前提交的是硬编码数据,表单输入未被收集,改用状态管理获取真实用户输入:
import { useState } from 'react'; const New = ({ inputs, title }) => { const [formData, setFormData] = useState({ code: "", article: "", price: "", vat: null, status: 1, company_id: 10 }); const handleInputChange = (e) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: name === 'price' ? Number(value) : value })); }; const handleClick = (e) => { e.preventDefault(); fetch("https://api.factarni.tn/article/create", { method: "POST", body: JSON.stringify(formData), headers: { Authorization: "Bearer ...", "Content-Type": "application/json" }, }) .then(response => { if (!response.ok) throw new Error(`状态码: ${response.status}`); return response.json(); }) .then(data => console.log('提交成功:', data)) .catch(err => console.error('提交失败:', err)); }; return ( <div className="New"> <Sidebar /> <div className="newContainer"> <Navbar /> <div className="top"> <h1>{title}</h1> </div> <div className="bottom"> <div className="right"> <form> {inputs.map((input) => ( <div className="formInput" key={input.id}> <label>{input.label} </label> <input type={input.type} placeholder={input.placeholder} name={input.name} // 确保inputs数组包含对应字段名(如code、article) value={formData[input.name]} onChange={handleInputChange} /> </div> ))} <button onClick={handleClick}>Add</button> </form> </div> </div> </div> </div> ); }; export default New;
5. 捕获响应错误
添加错误处理逻辑,打印详细错误信息,帮助定位问题:
fetch(...) .then(response => { if (!response.ok) { return response.text().then(text => { throw new Error(`请求失败: ${response.status} - ${text}`); }); } return response.json(); }) .then(data => console.log(data)) .catch(error => console.error('错误详情:', error));
内容的提问来源于stack exchange,提问作者Darkpsinight
相关产品推荐
相关产品推荐

