React点击卡片组件实例后如何隐藏其他同类型卡片?
问题:点击卡片展开后隐藏其他卡片实例
我是一名待业的初级开发者,正在制作个人作品集。使用react-card-flip实现了可翻转放大的卡片组件,通过axios请求GitHub API生成多个卡片实例。当前遇到的问题是:点击卡片使其翻转展开后,无法隐藏其余所有卡片。
我知道React中不应该用querySelector这类DOM操作,即便尝试了也没成功,希望不用彻底重构现有代码来解决这个问题。我的思路是给除点击卡片外的所有实例添加hidden类(包含display: none),但方法可能有误。
现有代码
Projects页面
const Projects = () => { let cards = document.getElementsByClassName("list") const [Repos, setRepos] = useState([]); const Hider = (id) => { console.log(cards) // cards.classList.add('hidden') } useEffect(() => { axios.get("https://api.github.com/users/Leehamb99/repos").then((response) => { setRepos(response.data) }) .catch(err => { console.log(err) }) }, []); return ( <> {Repos.map((repo, index) => { return ( <div className="list" onClick={() => { Hider(index) }}> <ProjectCard key={index} name={repo.name} /> </div> ) })} </> ) };
ProjectCard组件
const ProjectCard = (props) => { const [flip, setFlip] = useState(false); return ( <ReactCardFlip isFlipped={flip} flipDirection="vertical"> <div style={{ display: 'flex', flexWrap: 'wrap', width: '75px', height: '75px', background: 'gray', fontSize: '18px', color: 'black', margin: '15px', borderRadius: '4px', textAlign: 'center', padding: '20px', boxShadow: '10px' }} onClick={() => setFlip(!flip)}> {props.name} </div> <div style={{ width: '500px', height: '500px', background: '#F0EDE4', fontSize: '18px', color: 'black', margin: '15px', borderRadius: '4px', textAlign: 'center', padding: '20px', boxShadow: '10px' }} onClick={() => setFlip(!flip)}> Computer Science Portal. </div> </ReactCardFlip> ); }
解决方案(基于现有代码修改,无需DOM操作)
核心思路是用React状态跟踪当前激活的卡片,通过状态控制非激活卡片的显示/隐藏,同时联动卡片的翻转状态:
1. 修改Projects组件
- 添加
activeCardIndex状态,存储当前点击的卡片索引(初始为null表示无激活卡片) - 修改
Hider函数,更新激活索引(点击已激活的卡片时重置为null,实现关闭) - 渲染时,给非当前激活的卡片添加
hidden类;同时把激活状态和翻转控制传递给子组件
修改后的Projects代码:
const Projects = () => { const [Repos, setRepos] = useState([]); // 新增状态:跟踪当前激活的卡片索引,null表示无激活 const [activeCardIndex, setActiveCardIndex] = useState(null); const Hider = (id) => { // 点击已激活的卡片,重置状态;否则设置为当前索引 setActiveCardIndex(prev => prev === id ? null : id); } useEffect(() => { axios.get("https://api.github.com/users/Leehamb99/repos").then((response) => { setRepos(response.data) }) .catch(err => { console.log(err) }) }, []); return ( <> {Repos.map((repo, index) => { // 判断是否为当前激活卡片,非激活则加hidden类 const isActive = activeCardIndex === index; const listClass = isActive ? "list" : "list hidden"; return ( <div className={listClass} onClick={() => Hider(index)} key={index}> {/* 把激活状态和翻转控制传递给子组件 */} <ProjectCard name={repo.name} isFlipped={isActive} onFlipToggle={() => Hider(index)} /> </div> ) })} </> ) };
2. 修改ProjectCard组件
- 移除组件内部的
flip状态,改用父组件传递的isFlipped属性控制翻转 - 点击卡片时调用父组件传递的
onFlipToggle方法,同步更新激活状态
修改后的ProjectCard代码:
const ProjectCard = (props) => { // 不再维护内部flip状态,直接用父组件传入的isFlipped return ( <ReactCardFlip isFlipped={props.isFlipped} flipDirection="vertical"> <div style={{ display: 'flex', flexWrap: 'wrap', width: '75px', height: '75px', background: 'gray', fontSize: '18px', color: 'black', margin: '15px', borderRadius: '4px', textAlign: 'center', padding: '20px', boxShadow: '10px' }} onClick={props.onFlipToggle}> {props.name} </div> <div style={{ width: '500px', height: '500px', background: '#F0EDE4', fontSize: '18px', color: 'black', margin: '15px', borderRadius: '4px', textAlign: 'center', padding: '20px', boxShadow: '10px' }} onClick={props.onFlipToggle}> Computer Science Portal. </div> </ReactCardFlip> ); }
3. 补充CSS
确保你的CSS中有hidden类:
.hidden { display: none; }
逻辑说明
- 点击卡片时,父组件更新
activeCardIndex,非激活卡片自动加上hidden类隐藏 - 卡片的翻转状态由父组件的激活状态控制,点击已激活的卡片会重置状态,隐藏的卡片重新显示,当前卡片恢复原状
内容的提问来源于stack exchange,提问作者Liam Bolton
相关产品推荐
相关产品推荐

