React Redux Toolkit(RTK)动态分类实现及报错解决
解决方案
问题根源
组件初始化时,useGetSingleProductQuery 还处于请求状态,getSingleProduct 是 undefined,所以 useState(getSingleProduct?.category) 的初始值为 undefined。而JSX中通过 isFetching 和 error 的判断,只有当请求完成、数据加载成功后才会渲染包含 getSingleProduct.category 的内容,这时候 getSingleProduct 已经有有效值,所以能正常访问。
另外你当前的 useEffect 依赖为空数组,只会执行一次,且执行时 url 中的 matchCategory 是初始的 undefined,导致请求无效,后续也不会重新触发请求。
优化方案(基于RTK Query实现)
既然已经用了Redux Toolkit和RTK Query,完全不需要混用axios,直接利用已定义的 useGetRelatedProductQuery 来实现相关商品获取,逻辑更简洁且符合RTK Query的设计规范:
修改后的完整代码
import React from "react"; import { useGetSingleProductQuery, useGetRelatedProductQuery, } from "../../features/productsApi"; import { useParams } from "react-router-dom"; function ProductDetails() { const { id } = useParams(); // 获取单个商品数据 const { data: getSingleProduct, isFetching: isSingleFetching, error: singleError, } = useGetSingleProductQuery(id); // 获取同分类商品:当getSingleProduct存在时才发起请求,避免参数为空 const { data: relatedProducts, isFetching: isRelatedFetching, error: relatedError, } = useGetRelatedProductQuery(getSingleProduct?.category, { skip: !getSingleProduct, // 商品数据未加载时跳过请求 }); if (isSingleFetching) return <p>Loading product details...</p>; if (singleError) return <p>Failed to load product details</p>; return ( <div className="row mt-5"> {/* 商品详情区域 */} <div className="col-md-6 mb-5 text-center"> <img className="w-100" style={{ height: "300px", objectFit: "contain" }} src={getSingleProduct.image} alt={getSingleProduct.title} /> <div>{getSingleProduct.title.substring(0, 20)}</div> <p>{getSingleProduct.description}</p> <p>Category: {getSingleProduct.category}</p> </div> {/* 相关商品区域 */} <div className="col-md-6"> <h3>Related Products</h3> {isRelatedFetching ? ( <p>Loading related products...</p> ) : relatedError ? ( <p>Failed to load related products</p> ) : ( <div className="row"> {relatedProducts?.map(product => ( <div key={product.id} className="col-md-6 mb-3"> <img className="w-100" style={{ height: "150px", objectFit: "contain" }} src={product.image} alt={product.title} /> <p>{product.title.substring(0, 15)}</p> </div> ))} </div> )} </div> </div> ); } export default ProductDetails;
关键修改点
- 移除了多余的
useState和axios请求,完全用RTK Query的hook管理数据请求 - 使用
useGetRelatedProductQuery的skip选项,确保只有当单个商品数据加载完成后才发起相关商品请求 - 拆分了加载状态和错误状态,分别处理商品详情和相关商品的加载/错误情况
- 优化了JSX结构,清晰区分商品详情和相关商品展示区域
补充说明
如果你的 useGetRelatedProductQuery 还没有配置正确的请求参数,需要在 productsApi 中确保它的查询参数是分类名称,比如:
// 在features/productsApi.js中定义相关商品的查询 export const productsApi = createApi({ reducerPath: 'productsApi', baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:5000/' }), endpoints: (builder) => ({ // ...其他接口 getRelatedProduct: builder.query({ query: (category) => `products?category=${category}`, }), }), });
内容的提问来源于stack exchange,提问作者Omor Faruk
相关产品推荐
相关产品推荐

