react-bootstrap渲染图片出现重复输出(12张而非4张)bug如何修复?
问题原因
- 同层级兄弟组件key重复:你上下两行的4个Col组件全部使用了相同的设施Id作为key值,React要求同层级兄弟元素的key必须唯一,否则diff算法无法正确识别需要卸载的旧节点,导致历史渲染的图片节点不断累积,每切换一次按钮就多渲染4张,切换3次就会出现12张的问题。
- 按钮取值逻辑错误:React-Bootstrap的Button是封装组件,点击时
e.target可能指向按钮内部的文本节点而非按钮本身,会出现拿不到value的情况,导致匹配不到正确的设施数据。 - 额外说明:你第一个设施De'Spa的四个图片路径填的都是同一个,修复后会显示4张相同的图,如需不同请自行修改路径。
修复方案
- 给每个Col设置唯一key,拼接图片位置标识保证同层级key不重复
- 按钮点击事件用
e.currentTarget.value替代e.target.value,保证拿到正确绑定的按钮值 - 用
Array.find替代filter查找当前设施,性能更高,同时添加兜底判断避免匹配不到数据时报错 - 给img标签补充alt属性,符合前端规范
修复后完整代码
import { useState, useEffect } from 'react'; import { Container, Row, Col, Button } from 'react-bootstrap'; const facsInfo = [ { Id: "1", Title: "De'Spa", Description: "", upperleftimg:"./Images/DeSpa1.jpg", upperrightimg:"./Images/DeSpa1.jpg", bottomleftimg:"./Images/DeSpa1.jpg", bottomrightimg:"./Images/DeSpa1.jpg", }, { Id: "2", Title: "De'Resto", Description:" ", upperleftimg:"./Images/DeResto1.jpg", upperrightimg:"./Images/DeResto2.jpg", bottomleftimg:"./Images/DeResto3.jpg", bottomrightimg:"./Images/DeResto4.jpg", }, { Id: "3", Title: "Meeting Room", Description: "", Opentime:"Opening hours: 10.00 am – 8.00 pm", upperleftimg:"./Images/Room1.jpg", upperrightimg:"./Images/Room2.jpg", bottomleftimg:"./Images/Room3.jpg", bottomrightimg:"./Images/Room4.jpg", }, ] const Facilities = () => { const [currentId, setCurrentId] = useState("1"); useEffect(() => { console.log(currentId); }, [currentId]); const showSelectedFact = () => { const fac = facsInfo.find((x) => x.Id === currentId); if (!fac) return null; const { Title, Description, Opentime, Id } = fac; return ( <div key={Id}> <h1 className="fontSB">{Title}</h1> <p>{Description}</p><br></br> <p><b>{Opentime}</b></p> </div> ); }; const showSelectedUpperImage = () => { const fac = facsInfo.find((x) => x.Id === currentId); if (!fac) return null; const { upperleftimg, upperrightimg, Id } = fac; return ( <> <Col key={`${Id}-upper-left`} className="facsImage text-center" md={12} lg={6}> <img className="img-fluid" src={upperleftimg} alt={upperleftimg}></img> </Col> <Col key={`${Id}-upper-right`} className="facsImage text-center" md={12} lg={6}> <img className="img-fluid" src={upperrightimg} alt={upperrightimg}></img> </Col> </> ); }; const showSelectedBottomImage = () => { const fac = facsInfo.find((x) => x.Id === currentId); if (!fac) return null; const { bottomleftimg, bottomrightimg, Id } = fac; return ( <> <Col key={`${Id}-bottom-left`} className="facsImage text-center" sm={12} md={12} lg={6}> <img className="img-fluid" src={bottomleftimg} alt={bottomleftimg}></img> </Col> <Col key={`${Id}-bottom-right`} className="facsImage text-center" sm={12} md={12} lg={6}> <img className="img-fluid" src={bottomrightimg} alt={bottomrightimg}></img> </Col> </> ); }; return ( <> <Container fluid> <Row className="facsbuttwrapper text-center"> <Col sm={4} lg={4}> <Button value="1" variant="custom" onClick={(e) => setCurrentId(e.currentTarget.value)} > De'Spa </Button> </Col> <Col sm={4} lg={4}> <Button value="2" variant="custom" onClick={(e) => setCurrentId(e.currentTarget.value)} > De'Resto </Button> </Col> <Col sm={4} lg={4}> <Button value="3" variant="custom" onClick={(e) => setCurrentId(e.currentTarget.value)} > Meeting Room </Button> </Col> </Row> </Container> <Container fluid> <Row className="facsDetail fontReg"> <Col className="text-center" md={12} lg={12}> {showSelectedFact()} </Col> </Row> </Container> <Container fluid> <Row> {showSelectedUpperImage()} </Row> </Container> <Container fluid> <Row> {showSelectedBottomImage()} </Row> </Container> </> ) } export default Facilities
内容的提问来源于stack exchange,提问作者Kim San
相关产品推荐
相关产品推荐

