React电商项目中每2个ProductCard后渲染CompanyCard报错求助
问题描述
我正在开发一个电商商城,希望每渲染2个<ProductCard/>组件后,渲染一个<CompanyCard/>组件。期望的渲染顺序如下:
<ProductCard/> <ProductCard/> <CompanyCard/> <ProductCard/> <ProductCard/> <CompanyCard/> (and so on..)
但目前页面空白,控制台出现两个错误:
The above error occurred in the
<CompanyCard>component:
Uncaught TypeError: Cannot read properties of undefined (reading '_id')
以下是我的代码(使用React Redux):
function HomePage() { let counter = 0; const dispatch = useDispatch(); const productList = useSelector((state) => state.productList); const { error, loading, products } = productList; const companyList = useSelector((state) => state.companyList); const { companies } = companyList; useEffect(() => { dispatch(listProducts(), listCompanies()); }, [dispatch]); return ( <> <Navbar /> <div className="homePage"> <div className="centerItemsContainer"> <div className="productsContainer"> {products.map((product) => { counter++; if (counter % 4 === 0) { const companyIndex = counter / 4 - 1; const company = companies[companyIndex]; return ( <> <CompanyCard company={company} /> <ProductCard product={product} /> </> ); } else { return <ProductCard product={product} />; } })} </div> </div> </div> <Footer /> </> ); } export default HomePage;
问题分析与修复
1. 核心错误原因
- 商家数据未正确加载或索引越界:控制台报错说明传给
<CompanyCard>的company是undefined,要么是listCompanies没触发,要么是商家数组长度不够导致索引找不到对应元素。 - 计数器逻辑错误:在
map里修改全局counter,组件重渲染时会重置,而且逻辑是每4个产品才插商家卡,和需求的“每2个产品后插商家卡”完全不符。 - dispatch用法错误:
dispatch一次只能传一个action,你写的dispatch(listProducts(), listCompanies())只会执行第一个,第二个直接被忽略。
2. 分步修复
先修正dispatch调用
把两个dispatch分开写,确保两个接口都触发:
useEffect(() => { dispatch(listProducts()); dispatch(listCompanies()); }, [dispatch]);
重构渲染逻辑,实现正确顺序
放弃全局计数器,用数组索引来判断位置,同时处理边界情况避免报错:
function HomePage() { const dispatch = useDispatch(); const productList = useSelector((state) => state.productList); const { error, loading, products } = productList; const companyList = useSelector((state) => state.companyList); const { companies } = companyList; useEffect(() => { dispatch(listProducts()); dispatch(listCompanies()); }, [dispatch]); // 处理加载、错误、无数据状态,避免页面空白 if (loading) return <div>加载中...</div>; if (error) return <div>产品加载失败: {error}</div>; if (!companies || companies.length === 0) return <div>暂无商家信息</div>; // 构建最终渲染的元素数组 const renderItems = []; products.forEach((product, index) => { // 先添加当前产品卡片 renderItems.push(<ProductCard key={`product-${index}`} product={product} />); // 每2个产品后插入商家卡片(索引从0开始,所以用index+1判断) if ((index + 1) % 2 === 0) { // 计算商家索引,用取模循环使用商家数据,避免越界 const companyIndex = Math.floor((index + 1) / 2) - 1; const targetCompany = companies[companyIndex % companies.length]; if (targetCompany) { renderItems.push(<CompanyCard key={`company-${companyIndex}`} company={targetCompany} />); } } }); return ( <> <Navbar /> <div className="homePage"> <div className="centerItemsContainer"> <div className="productsContainer"> {renderItems} </div> </div> </div> <Footer /> </> ); } export default HomePage;
关键优化点
- 用
forEach构建渲染数组,比map更灵活处理“插入多个元素”的场景 - 增加加载、错误状态提示,解决页面空白问题
- 用
companyIndex % companies.length循环复用商家数据,彻底避免索引越界 - 给每个组件加唯一
key,符合React列表渲染规范
3. 额外建议
- 在
<CompanyCard>组件里加容错逻辑,比如当company为undefined时显示默认占位内容,避免组件崩溃 - 检查Redux中
listCompanies的action和reducer,确保商家数据被正确存入store
内容的提问来源于stack exchange,提问作者Martin Arreola
相关产品推荐
相关产品推荐

