React使用.map遍历渲染组件时prop传递异常,模态框仅显示最后一条数据
问题原因
你整个NewsCard组件只定义了一个全局的isModalOpen布尔状态,所有遍历生成的卡片模态框都共用这一个状态控制显隐。
当你点击任意卡片的「Read More」按钮把isModalOpen设为true后,所有新闻对应的模态框都会同时被切换为显示状态。而模态框一般是固定定位层级堆叠的,视觉上你只能看到最后一个渲染出来的模态框,也就是数组最后一项对应的内容,所以不管点哪个卡片,你看到的都是最后一篇新闻的信息。
解决方法
方法1:拆分独立子组件(更推荐)
把单张新闻卡片+对应模态框拆成独立的小组件,每个组件内部维护自己的isModalOpen状态,天然隔离互不干扰。
父组件只负责遍历传参即可:
// 父组件 NewsCard.js import React from 'react'; import { useNewsContext } from '../context/news-context'; import NewsCardItem from './NewsCardItem'; const NewsCard = () => { const { newsArticles, isLoading } = useNewsContext(); return ( <section className='news-section wrapper'> {newsArticles.map((item, index) => ( <NewsCardItem key={index} item={item} /> ))} </section> ); }; export default NewsCard;
// 子组件 NewsCardItem.js import React, { useState } from 'react'; const NewsCardItem = ({ item }) => { const [isModalOpen, setIsModalOpen] = useState(false); const { title, description, urlToImage, content } = item; const readMore = () => setIsModalOpen(true); const closeBtn = () => setIsModalOpen(false); return ( <div className='news-card'> <img className='news-image' src={urlToImage} alt={title} /> <h1>{title}</h1> <p>{description}</p> <button type='button' onClick={readMore}>Read More</button> <div className={isModalOpen ? 'news-modal' : 'news-modal news-modal__hidden'}> <div className='news-modal__card'> <h1>{title}</h1> <p>{content}</p> <button type='button' onClick={closeBtn}>Close</button> </div> </div> </div> ) } export default NewsCardItem;
方法2:状态存储当前激活的新闻索引
不拆组件的话,把原本的布尔状态改成存储当前点击的新闻索引,判断当前模态框是否为激活项再显示:
import React, { useState } from 'react'; import { useNewsContext } from '../context/news-context'; const NewsCard = () => { const { newsArticles, isLoading } = useNewsContext(); // 存储激活的新闻索引,null为没有激活 const [activeNewsIndex, setActiveNewsIndex] = useState(null); const readMore = (index) => { setActiveNewsIndex(index); }; const closeBtn = () => { setActiveNewsIndex(null); }; return ( <section className='news-section wrapper'> {newsArticles.map((item, index) => { const { title, description, urlToImage, content } = item; // 判断当前项是不是激活的项 const isCurrentModalOpen = activeNewsIndex === index; return ( <div key={index} className='news-card'> <img className='news-image' src={urlToImage} alt={title} /> <h1> {title} </h1> <p> {description} </p> <button type='button' onClick={() => readMore(index)}> Read More </button> <div className={isCurrentModalOpen ? 'news-modal' : 'news-modal news-modal__hidden'}> <div className='news-modal__card'> <h1> {title} </h1> <p> {content} </p> <button type='button' onClick={closeBtn}> Close </button> </div> </div> </div> ); })} </section> ); }; export default NewsCard;
内容的提问来源于stack exchange,提问作者anon03519124
相关产品推荐
相关产品推荐

