如何解构JSON数组>对象>数组并在React组件中渲染对应商品
解决JSON数据解构与分类商品渲染问题
问题背景
需要解构如下结构的JSON文件,获取"Bags"、"Shoes"这类分类名称,并根据传入的merch参数渲染对应分类的商品:
[ { "Bags": [ { "id": 1, "name": "Michael Kors Bag", "price": 235, "imgURL": "/imgs/03045643da82a42a4a5c86842f4b17f1.jpg" }, { "id": 2, "name": "Ted Baker Bag", "price": 495, "imgURL": "/imgs/4c176b2fa86bdcddf74822c2501bbcac.jpg" }, { "id": 3, "name": "Coach Bag", "price": 238, "imgURL": "/imgs/coach-jes-crossbody-signature-canvas-brown-black-59181.jpg" }, { "id": 4, "name": "Kate Spade Bag", "price": 35, "imgURL": "/imgs/10.jpg" } ] }, { "Shoes": [ { "id": 1, "name": "Michael Kors Bag", "price": 235, "imgURL": "/imgs/03045643da82a42a4a5c86842f4b17f1.jpg" }, { "id": 2, "name": "Ted Baker Bag", "price": 495, "imgURL": "/imgs/4c176b2fa86bdcddf74822c2501bbcac.jpg" }, { "id": 3, "name": "Coach Bag", "price": 238, "imgURL": "/imgs/coach-jes-crossbody-signature-canvas-brown-black-59181.jpg" }, { "id": 4, "name": "Kate Spade Bag", "price": 35, "imgURL": "/imgs/10.jpg" } ] } ]
路由传入参数的方式如下:
<Route path="/store" element={<Store merch="Bags" />} />
当前的Store.tsx无法正常工作,代码如下:
import storeItems from "../data/items.json"; import { Row, Col, Container } from "react-bootstrap"; import { StoreItem } from "../components/StoreItem"; import { useState } from "react"; type StoreProps = { merch: string; }; export function Store({ merch }: StoreProps) { const [data, setData] = useState([]); for (let i = 0; i < storeItems.length; i++) { let a = Object.values(storeItems[i]); console.log(a); } console.log(storeItems); return ( <> <Container className="mw-80 d-flex align-items-center justify-content-center p-0 flex-column mb-5"> <h1 className="m-5">Bags</h1> <Row md={2} xs={1} lg={3} className="g-3"> {storeItems.map((item) => ( <Col> <StoreItem key={item.id} {...item} /> </Col> ))} </Row> </Container> </> ); }
解决方案
1. 理解JSON结构
原始JSON是一个数组,每个元素是单键对象:键为分类名称(如"Bags"),值为对应分类的商品数组。需要根据merch参数匹配这个键,取出对应的商品列表。
2. 优化Store组件实现
不需要使用useState存储静态数据,直接在组件中计算出目标分类的商品即可,修改后的代码如下:
import storeItems from "../data/items.json"; import { Row, Col, Container } from "react-bootstrap"; import { StoreItem } from "../components/StoreItem"; type StoreProps = { merch: string; }; // 定义商品类型,提升类型安全性 type Product = { id: number; name: string; price: number; imgURL: string; }; export function Store({ merch }: StoreProps) { // 找到对应分类的商品数组 const products: Product[] = storeItems // 遍历数组,找到包含目标分类键的对象 .find(item => Object.keys(item).includes(merch)) // 取出该分类下的商品列表,若无匹配则返回空数组 ?.[merch] || []; return ( <> <Container className="mw-80 d-flex align-items-center justify-content-center p-0 flex-column mb-5"> {/* 动态渲染分类标题 */} <h1 className="m-5">{merch}</h1> <Row md={2} xs={1} lg={3} className="g-3"> {/* 遍历商品数组渲染StoreItem */} {products.map((product) => ( <Col key={product.id}> <StoreItem {...product} /> </Col> ))} </Row> </Container> </> ); }
关键修改点
- 移除了不必要的
useState,直接通过find方法匹配目标分类 - 添加了
Product类型定义,增强TypeScript类型检查 - 动态渲染分类标题(替换了硬编码的"Bags")
- 遍历对应分类的商品数组,而非原始的storeItems数组,确保只渲染目标分类的商品
- 处理了无匹配分类的情况,默认返回空数组避免报错
内容的提问来源于stack exchange,提问作者ether
相关产品推荐
相关产品推荐

