React自定义Hook中使用Axios获取单产品数据失败排查
问题排查与解决方案
核心问题分析
你遇到的产品名称无法显示的问题,主要由三个错误导致:
- 请求地址拼写错误:
getSingleProduct函数中请求后缀写成了.jason,正确格式应为.json,这会导致API请求失败,singleProduct始终为null。 - 未使用路由参数:当前
getSingleProduct硬编码请求ID为1048的产品,没有利用路由传来的id参数,无法动态获取对应产品的详情。 - useEffect依赖缺失:useEffect的依赖数组为空,当路由中的
id变化时,不会重新触发请求;同时未将getSingleProduct加入依赖,可能导致请求逻辑不更新。
修改后的完整代码
自定义Hook:useGetProduct.js
import { useState, useCallback } from 'react'; import axios from 'axios'; const BASE_URL = "https://makeup-api.herokuapp.com/api/v1/products"; const useGetProduct = () => { const [products, setProducts] = useState([]); const [singleProduct, setSingleProduct] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const getTopProducts = useCallback(() => { axios.get(`${BASE_URL}.json`, { params: { product_tags: 'Canadian', }, }) .then(response => setProducts(response.data)) .catch(err => console.error('获取热门产品失败:', err)); }, []); const getSingleProduct = useCallback((productId) => { setLoading(true); setError(null); // 修正拼写错误,并使用传入的productId参数 axios.get(`${BASE_URL}/${productId}.json`) .then(response => { setSingleProduct(response.data); setLoading(false); }) .catch(err => { console.error('获取单个产品失败:', err); setError(err.message); setLoading(false); }); }, []); return { products, getTopProducts, singleProduct, getSingleProduct, loading, error } }; export default useGetProduct;
Product组件:Product.js
import React, { useEffect } from "react"; import { useParams } from "react-router-dom"; import useGetProduct from "../hooks/useGetProduct"; const Product = () => { const { id } = useParams(); const { singleProduct, getSingleProduct, loading, error } = useGetProduct(); useEffect(() => { // 确保id存在时再发起请求 if (id) { getSingleProduct(id); } }, [id, getSingleProduct]); // 添加依赖,确保id变化时重新请求 // 处理不同状态的UI展示 if (loading) return <div>加载中...</div>; if (error) return <div>加载失败: {error}</div>; if (!singleProduct) return <div>未找到对应产品</div>; return ( <div> <p>Product: {singleProduct.name}</p> {/* 可扩展展示更多产品信息 */} <p>品牌: {singleProduct.brand}</p> <p>价格: ${singleProduct.price}</p> </div> ); }; export default Product;
关键修改说明
- 修正了API请求后缀的拼写错误,保证请求能正常响应。
- 让
getSingleProduct接收外部传入的productId参数,实现根据路由动态获取产品详情。 - 使用
useCallback包裹请求函数,避免组件重复渲染时创建新函数,同时让useEffect的依赖更稳定。 - 添加
loading和error状态,优化用户体验,明确展示请求的不同阶段状态。 - 完善useEffect的依赖数组,确保路由参数
id变化时自动重新发起请求。
内容的提问来源于stack exchange,提问作者Zohre Omidi
相关产品推荐
相关产品推荐

