React项目中无法展示浏览量Top2博客问题排查求助
问题分析与修复:无法仅展示浏览量Top2博客
问题根源
第二个
useEffect执行时机错误
第二个useEffect的依赖数组为空,只会在组件挂载时执行一次。但此时第一个useEffect的异步请求还未完成,popularResults仍是初始空数组,排序切片操作根本不会对后续请求回来的数据生效。sort方法的原地修改副作用Array.sort()是原地修改数组的方法,直接调用popularResults.sort()会修改原状态数组,违反React状态不可变的原则,可能引发意外的重渲染或状态混乱。
修复方案(推荐第一种)
方案一:请求完成后直接处理数据
在第一个useEffect的请求回调里,直接对返回的数据进行排序切片,再更新状态,无需额外的useEffect:
const [popularResults, setPopularResults] = useState([]); useEffect(() => { const fetchData = async () => { try { const res = await axios.get(`${appUrl}/service/listofblogs`); // 先复制数组,避免sort原地修改原数据,再排序取前2条 const sortedTopBlogs = [...res.data.blogData] .sort((a, b) => b.views - a.views) .slice(0, 2); setPopularResults(sortedTopBlogs); } catch (e) { console.log(e); } } fetchData(); }, []); // 后续组件渲染代码不变 const MostPopularBlogs = () => <div className='row'> <div className='trendingArea'> { popularResults.map (({id, blogdetails, views, createdAt }) => ( <a href="#!" onClick={(e) => { e.preventDefault(); // 阻止a标签默认跳转行为 navigate("popularBlogDetails", { state: { id, blogdetails, views, createdAt} }) }}> <div key={id} className='popularArea'> <ReactMarkdown children={blogdetails} className='dataDate renderElipsis tags readmoreLink views' remarkPlugins={[remarkGfm]} /> <div className='blogDate'> {moment(createdAt).format('DD-MMM-YYYY')} <a className='readmoreLink' onClick={(e) => { e.stopPropagation(); // 避免触发外层a标签的点击事件 navigate("popularBlogDetails", { state: { id, blogdetails, views, createdAt} }) }}> Read more → </a> <div className='blogViews'> {views > 999 ? (views / 1000).toFixed(2) + "K" : views} </div> </div> </div> </a> ))} </div> </div>
注:额外修复了a标签的默认跳转问题,避免点击时触发页面跳转;同时给内部"Read more"的a标签添加了stopPropagation,防止重复触发导航。
方案二:修正第二个useEffect的依赖
如果一定要保留两个useEffect,需要给第二个useEffect添加popularResults作为依赖,并处理空数组的情况:
const [popularResults, setPopularResults] = useState([]); useEffect(() => { const fetchData = async () => { try { const res = await axios.get(`${appUrl}/service/listofblogs`); setPopularResults(res.data.blogData); } catch (e) { console.log(e); } } fetchData(); }, []); useEffect(() => { // 只有当数据存在时才处理 if (popularResults.length === 0) return; // 复制数组后排序切片 const sortedTopBlogs = [...popularResults] .sort((a, b) => b.views - a.views) .slice(0, 2); setPopularResults(sortedTopBlogs); }, [popularResults]); // 组件渲染代码不变
总结
方案一逻辑更简洁,避免了额外的状态更新触发,是更优的选择。核心是保证数据处理时机正确,同时遵循React状态不可变的原则,避免原地修改状态数组。
内容的提问来源于stack exchange,提问作者soccerway
相关产品推荐
相关产品推荐

