如何在map函数中使用React-Bootstrap Modal?解决内容显示异常
解决模态框点击任意按钮只显示第一条数据的问题
问题根源是你给每个列表项都渲染了一个ModalPhoto组件,且所有模态框共用同一个show状态。点击任意按钮触发setShow(true)时,所有模态框都会被打开并重叠在一起,视觉上只会显示其中一个(你看到的第一条),这完全没必要。
正确的做法是只渲染一个模态框,用状态存储当前要展示的项的数据,点击按钮时把对应项的数据存入状态,再打开模态框。
修改后的父组件代码
import { useState } from 'react'; import ModalPhoto from './modal'; function YourTableComponent() { // 新增状态存储当前选中的项 const [selectedItem, setSelectedItem] = useState(null); const [show, setShow] = useState(false); const openModal = (item) => { // 先存入当前点击的项,再打开模态框 setSelectedItem(item); setShow(true); }; return ( <> <Table> <thead> <tr> <th>miniaturka</th> <th>nazwa</th> <th>cena</th> </tr> </thead> <tbody> {/* 修正map参数命名,避免变量名冲突:item为当前项,index为索引 */} {zestawy.map((item, index) => { return ( <tr key={item.id}> <th> <Image src={`/nowemodule/${index}.webp`} width={100} height={100} /> </th> <td> {/* 点击时传入当前项数据 */} <Button onClick={() => openModal(item)}> {item.name} {item.wielkości} </Button> </td> <td>{cena(index).toFixed(2)} zł</td> </tr> ); })} </tbody> </Table> {/* 只渲染一个模态框,放在循环外部,使用选中项的数据 */} <ModalPhoto show={show} setShow={setShow} title={selectedItem?.name || ''} content={selectedItem?.description || ''} photo={selectedItem ? `/nowemodule/${zestawy.indexOf(selectedItem)}.webp` : ''} /> </> ); }
模态框组件(可小幅优化)
function ModalPhoto({ title, content, photo, show, setShow }) { const handleClose = () => setShow(false); return ( <Modal show={show} onHide={handleClose}> <Modal.Header closeButton> <Modal.Title>{title}</Modal.Title> </Modal.Header> <Modal.Body> <p>{content}</p> </Modal.Body> {/* 图片存在时再渲染,避免空值报错 */} {photo && <Image src={photo} width={100} height={100} />} <Modal.Footer> <Button variant="secondary" onClick={handleClose}>Close</Button> </Modal.Footer> </Modal> ); } export default ModalPhoto;
关键改动说明
- 新增
selectedItem状态,专门存储当前点击项的完整数据,彻底避免多个模态框的数据冲突 - 把
ModalPhoto移到列表循环外部,只渲染一个模态框,减少不必要的DOM节点 - 修改按钮点击事件,通过箭头函数把当前项传入
openModal,确保打开的是对应项的内容 - 用可选链
?.和空值判断处理selectedItem为空的情况,避免页面报错 - 修正map的参数命名,解决原代码中变量名重复导致的混淆问题
内容的提问来源于stack exchange,提问作者user19358070
相关产品推荐
相关产品推荐

