React Gallery Filter刷新后All分类无法显示全部内容的问题
问题分析与修复方案
问题原因
- 异步setState导致初始数据错误:Project组件中,初始化的
useEffect里先调用setData(GalleryData),紧接着执行setFiltered(data)。但React的setState是异步操作,此时data仍然是初始的空数组,导致filtered被设置为空。 - 过滤逻辑未监听数据变化:Filter组件的
useEffect仅监听activeButton的变化,页面初始化时data还未完成更新,无法触发正确的过滤;同时当data后续更新时,也不会重新执行过滤逻辑。
修复步骤
1. 修正Project组件的初始化逻辑
直接将data的初始状态设置为GalleryData,省去不必要的useEffect,确保页面加载时就有完整数据:
import Filter from './Filter'; import { useState } from 'react'; const [data, setData] = useState(GalleryData); const [filtered, setFiltered] = useState(GalleryData); const [activeButton, setActive] = useState('all'); return ( <section className='projects' id='projects'> <div className="project-container"> <div className="heading-project">Projects</div> <div className="selection"> <Filter data={data} setFiltered={setFiltered} activeButton={activeButton} setActive={setActive} /> </div> {/* 补充渲染filtered内容的代码,示例: <div className="gallery"> {filtered.map(item => ( // 单个项目渲染逻辑 ))} </div> */} </div> </section> );
2. 完善Filter组件的依赖监听
给Filter组件的useEffect添加data作为依赖,确保数据或分类按钮变化时,都能重新执行过滤逻辑:
import React, { useEffect } from 'react' export default function Filter({setActive, activeButton, setFiltered, data}) { useEffect(()=>{ if(activeButton === 'all'){ setFiltered(data); return; } const filteredItems = data.filter((item)=> item.type.includes(activeButton) ); setFiltered(filteredItems); },[activeButton, data]); // 添加data到依赖数组 return ( <div className="filter-container"> <div className={activeButton === 'all' ? "active" : "list"} onClick={()=> setActive('all')}>All</div> <div className={activeButton === 'UI/UX' ? "active" : "list"} onClick={()=> setActive('UI/UX')}>UI/UX</div> <div className={activeButton === 'Website' ? "active" : "list"} onClick={()=> setActive('Website')}>Website</div> <div className={activeButton === 'Coding' ? "active" : "list"} onClick={()=> setActive('Coding')}>Coding</div> </div> ) }
额外说明
如果后续GalleryData需要通过异步请求获取(比如从API拉取),可以保留useEffect,修改为:
useEffect(()=>{ // 假设fetchData是异步获取数据的函数 fetchData().then(res => { setData(res); setFiltered(res); // 直接用获取到的数据设置filtered }); },[])
内容的提问来源于stack exchange,提问作者achen20
相关产品推荐
相关产品推荐

