如何为React商家列表项添加查看详情按钮并调用API?
实现React商家卡片的“查看详情”功能
嘿,这事儿不难,我给你拆解成几个步骤,一步步来实现:
1. 给商家卡片添加Materialize风格的“查看”按钮
首先,在你的BusinessCard组件里,把“查看”按钮加进去,用Materialize的按钮样式就行。记得把商家的id作为参数传给点击事件处理函数:
// BusinessCard.jsx const BusinessCard = ({ business, onViewDetails }) => { return ( <div className="card small"> <div className="card-content"> <span className="card-title">{business.name}</span> <p>地址:{business.address}</p> <p>评分:{business.rating}</p> </div> <div className="card-action"> {/* Materialize风格按钮,绑定点击事件并传入商家id */} <button className="waves-effect waves-light btn" onClick={() => onViewDetails(business.id)} > 查看详情 </button> </div> </div> ); }; export default BusinessCard;
2. 在父组件中实现详情请求逻辑
接下来,在渲染商家列表的父组件里,我们需要管理详情数据、加载状态和错误状态,同时写一个发送API请求的函数:
// BusinessList.jsx import { useState } from 'react'; import BusinessCard from './BusinessCard'; const BusinessList = ({ businesses }) => { // 状态管理:选中的商家详情、加载状态、错误信息 const [selectedBusiness, setSelectedBusiness] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); // 发送请求获取商家详情的函数 const handleViewDetails = async (businessId) => { setIsLoading(true); setError(null); setSelectedBusiness(null); try { // 使用AbortController防止组件卸载后请求仍在进行 const controller = new AbortController(); const signal = controller.signal; const response = await fetch(`/businesses/${businessId}`, { signal }); if (!response.ok) { throw new Error('获取详情失败,请稍后重试'); } const data = await response.json(); setSelectedBusiness(data); } catch (err) { // 排除用户主动取消请求的情况 if (err.name !== 'AbortError') { setError(err.message); } } finally { setIsLoading(false); } }; return ( <div className="row"> {/* 渲染商家卡片列表 */} {businesses.map(business => ( <div key={business.id} className="col s12 m6 l4"> <BusinessCard business={business} onViewDetails={handleViewDetails} /> </div> ))} {/* 展示加载状态 */} {isLoading && <div className="progress"><div className="indeterminate"></div></div>} {/* 展示错误信息 */} {error && <div className="red-text center-align">{error}</div>} {/* 展示商家详情(用Materialize模态框更友好) */} {selectedBusiness && ( <div className="modal open"> <div className="modal-content"> <h4>{selectedBusiness.name}</h4> <p>完整地址:{selectedBusiness.fullAddress}</p> <p>联系方式:{selectedBusiness.phone}</p> <p>营业时间:{selectedBusiness.hours}</p> {/* 其他你需要展示的属性 */} </div> <div className="modal-footer"> <button className="modal-close waves-effect waves-green btn-flat" onClick={() => setSelectedBusiness(null)} > 关闭 </button> </div> </div> )} </div> ); }; export default BusinessList;
3. 额外优化点
- Materialize模态框初始化:如果你用的是Materialize的模态框,记得在组件挂载时初始化它(可以用
useEffect),或者使用Materialize的React封装库,这样模态框的显示/隐藏会更顺畅。 - 避免重复请求:可以给按钮加个禁用状态,在
isLoading为true时禁用按钮,防止用户多次点击。 - axios替代fetch:如果你习惯用axios,请求逻辑可以改成这样:
import axios from 'axios'; // ... const handleViewDetails = async (businessId) => { setIsLoading(true); setError(null); setSelectedBusiness(null); try { const response = await axios.get(`/businesses/${businessId}`); setSelectedBusiness(response.data); } catch (err) { setError(err.response?.data?.message || '获取详情失败'); } finally { setIsLoading(false); } }; // ...
这样一套下来,用户点击“查看”按钮就能获取对应商家的完整详情,并且有加载状态和错误提示,体验也不错~
内容的提问来源于stack exchange,提问作者OlatunjiYSO
相关产品推荐
相关产品推荐

