React前端Fetch请求Node.js后端报错:非有效JSON(Unexpected token '<')
解决React fetch请求返回HTML而非JSON的SyntaxError错误
问题场景
使用React开发前端、Node.js开发后端,通过前端useEffect钩子中的fetch函数从后端获取数据时,触发错误:
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON"
前端代码
import { useEffect, useState } from "react"; import Item from "./item"; import style from "./show-item.module.css"; const ShowItem = (props) => { const [orders, setOrders] = useState([]); useEffect(() => { fetch("/") .then((res) => { if(res.ok){ console.log('ok') return res.json() } }).then(result => console.log(result)) .catch((err) => console.log(err)); }, []); return ( <ul className={style["ul-item"]}> {orders.map((item) => ( <Item key={item.id} id={item.id} name={item.name} detail={item.detail} price={item.price} amount={1} /> ))} </ul> ); }; export default ShowItem;
代理配置(package.json)
"proxy": "http://localhost:5000",
后端代码
const adminRouts = require('./routes/admin'); const shopRouts = require('./routes/shop'); const shefRouts = require('./routes/chef'); const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json(), bodyParser.urlencoded({ extended: false })); const port = process.env.PORT || 5000; app.use('/admin',adminRouts); app.use('/shef', shefRouts); app.use(shopRouts); console.log('listen ', port) app.listen(port);
厨师路由(shef)代码
const express = require("express"); const router = express.Router(); const order = [ { id: 1, name: "הלחם שלנו", detail: "לחם פראנה באפייה מסורתית,שמן זית ומטבלים טעימים", price: 26, }, ]; router.use("/", (req, res, next) => { console.log('here'); res.json(order); }); module.exports = router;
错误原因
- 前端请求的是根路径
/,但后端未配置该路径返回JSON的路由。由于React代理的特性,当后端没有匹配的路由时,请求会被转发到前端的index.html,导致返回的是HTML文本而非JSON,解析时触发语法错误。 - 实际提供JSON数据的接口路径是
/shef(后端通过app.use('/shef', shefRouts)挂载路由,结合shef路由内部的根路径配置)。
解决方案
1. 修正前端请求路径
将fetch("/")改为fetch("/shef"),指向正确的后端接口,同时补充将数据更新到state的逻辑:
useEffect(() => { fetch("/shef") .then((res) => { if(res.ok){ console.log('ok') return res.json() } throw new Error('请求状态异常') }).then(result => { console.log(result) setOrders(result) }) .catch((err) => console.log(err)); }, []);
2. 完善错误处理逻辑
在第一个then中,当res.ok为false时主动抛出错误,确保异常能被catch捕获,避免后续逻辑处理undefined。
3. 验证后端接口
直接在浏览器访问http://localhost:5000/shef,确认返回的是JSON格式数据,确保后端路由正常工作。
最终修改后的前端代码
import { useEffect, useState } from "react"; import Item from "./item"; import style from "./show-item.module.css"; const ShowItem = (props) => { const [orders, setOrders] = useState([]); useEffect(() => { fetch("/shef") .then((res) => { if(res.ok){ console.log('ok') return res.json() } throw new Error(`请求失败,状态码:${res.status}`) }).then(result => { console.log(result) setOrders(result) }) .catch((err) => console.log(err)); }, []); return ( <ul className={style["ul-item"]}> {orders.map((item) => ( <Item key={item.id} id={item.id} name={item.name} detail={item.detail} price={item.price} amount={1} /> ))} </ul> ); }; export default ShowItem;
内容的提问来源于stack exchange,提问作者Matan Fadida
相关产品推荐
相关产品推荐

