如何解决Express.js取数返回undefined及React数据获取失败问题?
问题排查与解决方案
1. 前后端接口路径不匹配(核心问题)
后端定义的接口是/products/:productId(复数形式),但前端请求的路径是/product/${productId}(单数形式),这会导致请求返回404,自然无法获取数据。
修正前端路径:
// 改为复数products,若前端运行在不同端口,需补充完整后端地址 const url = `http://localhost:3001/products/${productId}`;
也可在React项目的package.json中添加代理配置,避免每次写完整URL:
"proxy": "http://localhost:3001"
配置后前端可直接写/products/${productId}。
2. 异步函数处理错误
fetchProduct是异步函数,直接执行const product = fetchProduct(url)得到的是Promise对象而非实际数据,且React组件不能在渲染阶段直接执行异步逻辑,需用useEffect触发请求:
修正后的fetch写法:
import { useState, useEffect } from 'react'; // 组件内部代码 const [product, setProduct] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchProduct = async () => { try { setLoading(true); const response = await fetch(`http://localhost:3001/products/${productId}`); if (!response.ok) { throw new Error(`请求失败:${response.status}`); } const data = await response.json(); setProduct(data); } catch(err) { setError(err.message); } finally { setLoading(false); } }; fetchProduct(); }, [productId]); // 依赖productId,ID变化时重新请求 // 渲染阶段处理状态 if (loading) return <div>加载中...</div>; if (error) return <div>错误:{error}</div>; return <div>{JSON.stringify(product)}</div>;
3. useAxios的使用问题
若使用第三方useAxios钩子,需确保:
- 请求路径修正为
/products/${productId} - 配置正确的后端baseURL
示例:
const [{data, loading, error}] = useAxios({ url: `/products/${productId}`, baseURL: 'http://localhost:3001' });
4. 后端代码优化与修复
4.1 完善错误响应机制
当前后端出错时仅在控制台打印错误,未向前端返回错误状态,导致前端无法感知问题:
app.get('/products/:productId', (req, res) => { console.log('request recieved'); const productId = req.params.productId; const query = 'SELECT * FROM products WHERE product_id = ?'; database.query(query, [productId], (err, result) => { if (err) { console.log(err); return res.status(500).json({ error: err.message }); // 返回错误响应 } console.log(result); res.json(result); // 用res.json更规范,自动设置Content-Type }); });
4.2 修复SQL注入风险
直接拼接参数到SQL语句存在严重安全漏洞,必须使用参数化查询(以MySQL为例):
// 用?作为占位符,参数放在数组中传入 const query = 'SELECT * FROM products WHERE product_id = ?'; database.query(query, [productId], (err, result) => { // 处理逻辑 });
4.3 优化服务器监听配置
app.listen(PORT, 'localhost')仅监听本地回环地址,若前端通过代理或其他设备访问会失败,建议修改为:
app.listen(PORT, '0.0.0.0', () => { console.log(`服务器运行在 http://localhost:${PORT}`); });
验证步骤
- 先测试后端接口:用浏览器或Postman访问
http://localhost:3001/products/1(替换1为实际存在的productId),确认能返回正确JSON数据。 - 修正前端路径和异步逻辑后重启项目,查看控制台报错信息与网络请求状态。
内容的提问来源于stack exchange,提问作者Daan van der Blom
相关产品推荐
相关产品推荐

