You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React JS中如何从JSON文件获取嵌套对象?

解决React中访问嵌套JSON对象及产品详情页展示问题

我来帮你一步步搞定这两个问题:访问嵌套JSON对象报错,以及点击产品展示详情页的功能实现。

一、修复嵌套对象访问报错的问题

你现在用{this.props.product[detailPage]}报错的核心原因是:detailPage是JSON里的键名,属于字符串,但你没加引号把它当作字符串使用。而且detailPage是一个数组,直接输出会显示[object Object],得访问里面的具体属性才行。

正确写法有两种:

  1. 推荐使用点语法(更直观):
// 先判断detailPage是否存在,避免数据未加载时的报错
{this.props.product.detailPage && this.props.product.detailPage[0].productDetail}
  1. 方括号语法(需要给键名加引号):
{this.props.product['detailPage'] && this.props.product['detailPage'][0].productDetail}

如果想临时输出整个detailPage的内容,可以用JSON.stringify格式化显示:

{this.props.product.detailPage && JSON.stringify(this.props.product.detailPage)}

二、实现点击产品展示单个详情页的功能

你当前代码里,Products组件的productdetails状态无论真假都渲染同一个组件,这逻辑不对。我们需要调整状态管理和组件渲染逻辑:

1. 修改Products组件的状态与方法

在Products组件里新增selectedProduct状态存储选中的产品,同时修正回调方法接收选中的产品:

export default class Products extends React.Component {
  constructor() {
    super();
    this.state = {
      productdetails: false,
      selectedProduct: null // 新增状态:存储选中的产品
    }
  }

  // 修改方法,接收选中的产品并更新状态
  handleinputdata(selectedProduct) {
    this.setState({
      productdetails: true,
      selectedProduct: selectedProduct
    });
  }

  // 新增返回列表的方法
  handleBack() {
    this.setState({ productdetails: false, selectedProduct: null });
  }

  render() {
    const { productdetails, selectedProduct } = this.state;
    let status;
    
    // 根据状态渲染列表页/详情页
    if (!productdetails) {
      status = <ProductsDetailComponent onUserInputs={this.handleinputdata.bind(this)} />;
    } else {
      status = <ProductSingleDetail product={selectedProduct} onBack={this.handleBack.bind(this)} />;
    }

    return (
      <Grid>
        <Row>
          <Col sm={12} className="text-center">
            <h2>MEN'S STYLES</h2>
            <p>To Make a Lasting Impression</p>
          </Col>
        </Row>
        {status}
      </Grid>
    );
  }
}

2. 更新ProductDetailData组件的点击逻辑

在ProductDetailData的点击方法里,把当前产品传递给父组件的回调:

class ProductDetailData extends React.Component {
  handleClick() {
    // 将当前选中的产品传递给父组件
    this.props.onUserInputs(this.props.product);
  }

  render() {
    const { title, img, des, rs, buy, details, id, detailPage } = this.props.product;
    return (
      <Col xs={12} sm={3} className="text-center product-list">
        <Card>
          <CardImg src={img} alt="product img" />
          ID - {id} <br/>
          img - {img} <br/>
          title - {title} <br/>
          des - {des} <br/>
          rs - {rs} <br/>
          buy - {buy} <br/>
          details - {details} <br/>
          {/* 正确访问嵌套属性 */}
          材质:{detailPage && detailPage[0].productDetail} <br/>
          <Link to="/">
            <CardTitle>{title}</CardTitle>
          </Link>
          <CardText>{des}</CardText>
          <CardText>Rs : {rs} /-</CardText>
          <Button className='btn btn-danger'>{buy}</Button> &nbsp;
          <Button onClick={this.handleClick.bind(this)} className="btn btn-primary">
            {details}
          </Button>
        </Card>
      </Col>
    )
  }
}

3. 创建单个产品详情组件ProductSingleDetail

新建一个组件专门展示选中产品的详细信息:

class ProductSingleDetail extends React.Component {
  render() {
    const product = this.props.product;
    if (!product) return <div>加载中...</div>;
    
    const detail = product.detailPage[0];
    return (
      <Row className="product-detail p-4">
        <Col sm={6}>
          <img src={product.img} alt={product.title} className="img-fluid" />
        </Col>
        <Col sm={6}>
          <h3>{product.title}</h3>
          <p className="text-muted">{product.des}</p>
          <h4 className="text-danger">Rs {product.rs} /-</h4>
          <hr />
          <h5>产品详情</h5>
          <ul className="list-unstyled">
            <li><strong>材质:</strong>{detail.productDetail}</li>
            <li><strong>库存:</strong>{detail.qty}</li>
            <li><strong>尺码:</strong>{detail.size}</li>
            <li><strong>颜色:</strong>{detail.color}</li>
          </ul>
          <Button className='btn btn-danger'>{detail.AddtoCart}</Button>
          <Button onClick={this.props.onBack} className='btn btn-secondary ml-2'>返回列表</Button>
        </Col>
      </Row>
    )
  }
}

4. 修正生命周期方法的问题

componentWillMount已经被React废弃,建议在ProductsDetailComponent里改用componentDidMount加载数据:

class ProductsDetailComponent extends React.Component {
  constructor() {
    super();
    this.state = { data: [] }
  }

  componentDidMount() { // 替换componentWillMount
    let url = "./products.json";
    Request.get(url)
      .then((res) => {
        this.setState({ data: res.body.data });
        console.log('加载的数据:', res.body.data);
      })
      .catch(function (err) {
        alert('加载产品数据失败:' + err);
      });
  }

  render() {
    return (
      <Row className="products-container">
        <Col sm={12}>
          { this.state.data.length > 0 ? (
              this.state.data.map( (product, index) => (
                <ProductDetailData key={index} product={product} onUserInputs={this.props.onUserInputs} />
              ))
            ) : (
              <div className="text-center py-5">加载产品中...</div>
            )
          }
        </Col>
      </Row>
    )
  }
}

三、关键修改点总结

  • 访问嵌套JSON对象时,确保键名是字符串(加引号或用点语法),数组要通过索引访问元素
  • 用状态管理控制列表页和详情页的切换,selectedProduct存储选中的产品数据
  • 替换废弃的componentWillMount为componentDidMount
  • 新增独立的详情组件,专门展示单个产品的完整信息

内容的提问来源于stack exchange,提问作者Developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:42:10