You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React项目中无法展示浏览量Top2博客问题排查求助

问题分析与修复:无法仅展示浏览量Top2博客

问题根源

  1. 第二个useEffect执行时机错误
    第二个useEffect的依赖数组为空,只会在组件挂载时执行一次。但此时第一个useEffect的异步请求还未完成,popularResults仍是初始空数组,排序切片操作根本不会对后续请求回来的数据生效。

  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:43:20