React中如何结合onClick按钮使用useParams跳转并按ID展示数据
问题根因
你代码里存在两个核心问题导致出现全量数据展示的情况:
- ID类型不匹配:
useParams()拿到的路由参数id是字符串类型,若接口返回的item.id为数字类型,全等判断item.id === id会直接返回false,导致过滤逻辑失效 - 账单详情区域未加过滤:你仅在顶部
explore-container区域加了ID过滤逻辑,下方核心账单展示的bills-container > .item-list区域直接对全量items.items做了遍历,所以会渲染所有接口返回的数据
修复步骤
直接修改Billing.js代码即可:
- 提前统一ID类型并过滤出当前要展示的账单数据,避免重复写过滤逻辑
- 替换全量遍历逻辑,只渲染过滤后的单条账单数据
修改后的核心代码
import React, { useState } from "react"; import "./Bill.css"; import { Link, useParams } from "react-router-dom"; import { connect } from "react-redux"; function BillList({ items }) { const [counter, setCounter] = useState(1); // 从路由取id并转成数字,和接口返回的id类型保持一致 const { id } = useParams(); const targetId = Number(id); // 提前过滤出当前要展示的单条账单 const currentBill = items?.items?.find(item => item.id === targetId); function Display(props) { return <label style={{ marginLeft: ".5rem" }}>{props.message}</label>; } // 加个loading/空状态判断,避免数据没加载完报错 if (!currentBill) return <div>加载中...</div> return ( <div className="bills"> <div className="explore-container"> {/* 这里不用再遍历了,直接用currentBill */} <div className="item-list" key={currentBill.id}> <h2>Title: {currentBill.title}</h2> <h4>price: {currentBill.price}</h4> </div> </div> <div className="main-title" style={{ textAlign: "center", justifyContent: "center", alignItems: "center", fontSize: 14, }} > <h1>Bakery</h1> <h1>Company Gbr</h1> <h1>Oranienburger Straße 120</h1> <h1>10119 Berlin</h1> </div> <div className="bills-container"> <div></div> {/* pass in the details */} <div className="item-list"> {/* 这里也不用遍历全量数据,直接用currentBill渲染 */} <React.Fragment key={currentBill.id}> <div className="bill-time"> <div className="bill"> <h4> {" "} <strong>Bill: </strong> {currentBill.billNumber} </h4> </div> <div className="time"> <h4> {" "} <strong>Time: </strong> {currentBill.created_datetime} </h4> </div> </div> ---------------------------------- ---------------------------------- ---------------------------------- -------------------- {/* Counter */} <div className="price-total"> <div className="title"> <h3> {" "} <strong>Title: </strong> {currentBill.title} </h3> <div className="counter"> <strong> <Display message={counter} />x </strong> </div> </div> <div className="increase"> <button onClick={() => setCounter(counter + 1)}>+</button> </div> <div className="decrease"> <button onClick={() => setCounter(Math.max(1, counter - 1))}>-</button> </div> {/* Price and total */} <div className="price"> <h4> <strong>Price: {parseFloat(currentBill.price)}€</strong> </h4> </div> <div className="total"> <h4>Total: {parseFloat(currentBill.price * counter)}€</h4> </div> </div> </React.Fragment> </div> </div> <div className="button-path"> <Link to="/items"> <div className="button"> <button className="main-button">Analyse Receipt</button> </div> </Link> </div> </div> ); } const mapStateToProps = (state) => { return { items: state.items, }; }; export default connect(mapStateToProps)(BillList);
额外优化点
- 给减号按钮加了最小值限制
Math.max(1, counter - 1),避免数量出现负数 - 移除了没用的冗余代码:比如组件末尾多余的
<Switch>、未使用的getItems引入和映射逻辑 - 加了空状态判断,避免数据还没加载完成时报错
内容的提问来源于stack exchange,提问作者karim Salim
相关产品推荐
相关产品推荐

