让Cursor都懵圈的React响应式设计

前阵子面试被问到Github好久没更新了,有些惭愧,因为上面都是我自己日常工作生活使用的,确实也没啥需求。

不过最近觉得足球应用可以做一些优化,正好开了144块Cursor会员,也在B站看了些使用教程,就在昨天开动了。

我的需求是这样的,拉取最近完成的比赛信息,展示、日期、场次,然后胜、平、负、让球胜平负、半全场、比分、总进球的赔率

但是A接口只能返回部分信息,让球胜平负、半全程、比分、总进球的赔率要调用B接口才能拿到

除了模态框架子的搭建我是用了之前写好的"代码片段"生成的,后面的都是跟Cursor说,让他搞,感受到了辅助开发的乐趣,一定程度上实现了异步。

有一次在修改后端node.js脚本时,因为请求接口被腾讯云拦截,我让他处理。他加了些代码,后面我让他去掉,结果他只去掉了前面的代码,没管后面的括号这些,导致文件格式有问题,我让他解决,他竟然删除了这个文件,又自以为是的进行了优化,格式是没问题了,好多功能直接无法使用。

旧代码和新写好的代码混在一起,还好Cursor能回退

然后就是翻页问题,因为翻页涉及到调用详情接口,拿到数据后在更新已有的列表数据。

我就反馈切换页面又问题,让他解决,好几次都不行,甚至有一次他自己加了调试代码,让我把控制台输出发给他,也不行,后面都扯到给表格加key强制更新上去了。

而且越来越差,最后变成加载数据后直接空白....

我一看越来越离谱,还是我自己来吧,发现核心问题在还是和React的响应式设计有关

我大概模拟一下,一开始数据结构是这样的

ini 复制代码
  const loadData = async () => {
    const response = await SFootball.getRecentMatches({ startDate, endDate });
    if (response.success) {
      setLoading(false);
      setState({
        list: response.data.list,
      }));

      // 获取第一页的详细赔率信息
      await loadCurrentPageOdds(1, 10);
    } else {
      setLoading(false);
    }
  };
 const loadCurrentPageOdds = async (currentPage: number, pageSize: number) => {
    // 获取当前页所有比赛的matchId
    const matchIds = state.list
      .slice(startIndex, endIndex)
      .map((match) => match.matchId);

    try {
      const oddsResponse = await SFootball.getMatchOddsDetail(matchIds);
      if (oddsResponse.success) {
        // 检查是否为mock数据
        if (oddsResponse.data.isMock) {
          message.warning("详情接口请求被拦截,现在使用的是mock数据");
          setState((prev) => ({ ...prev, isMock: true }));
        }

        // 从响应中提取详细赔率数据(排除isMock字段)
        const { isMock, ...oddsData } = oddsResponse.data;

        // 使用matchId更新数据
        const newData = [...state.list];
        for (let i = startIndex; i < pageSize * currentPage; i++) {
          const match = state.list[i];

          if (oddsData[match.matchId] && state.list[i]) {
            newData[i] = {
              ...match,
              ...oddsData[match.matchId],
            };
          }
        }
        setState(
          produce(prev, (draft) => {
            draft.list = newData;
          })
        )
      }
    } catch (error) {
      console.error("获取详细赔率失败:", error);
    }
  };

问题在于loadCurrentPageOdds中直接取state.list还是空数组,而且setState的时候只更新了list,没有更新page,就会导致翻页无效。

通常解决方案就是通过传参 await loadCurrentPageOdds(response.data.list, 1, 10); 但是翻页也要调用这个函数的

还有就是把list单独提出来, const [list, setList] = useState<NFootball.IFootballMatch[]>([]);

也可以通过传递函数的方式来缓解,但是依旧无法解决形参传递问题

ini 复制代码
setState(pre=>({...pre,...list}))

也可以和produce结合

ini 复制代码
setState(pre=>produce(pre,draf=>{

}))

这种方式我真的太久没有了,可能觉得produce已经完全替代了...

在通过loadData调用loadCurrentPageOdds

javascript 复制代码
setState(pre=>{
  console.log(pre)
  return pre
})

console.log(state.list)

前者打印的是改变后的数据,后者打印一个空数组

那么一道经典的面试题

scss 复制代码
  const [count, setCount] = useState<number>(1);
  <Button
          onClick={() => {
            setCount(count + 1);
            setCount(count + 1);
            setCount(count + 1);
          }}
        >
          点击{count}
        </Button>

问:每次点一次加几,答案:加1 问:如何不改变setCount数量做到每次点一次加3,答案:

javascript 复制代码
           setCount((pre) => pre + 1);
            setCount((pre) => pre + 1);
            setCount((pre) => pre + 1);

但说实话,大部人会有下意识的想到,进阶版面试题可以从上面的例子中演化出来。

比如能不去掉 await loadCurrentPageOdds(response.data.list, 1, 10);第一个形参

我试了下,最后只能尝试把所有逻辑都写进setState里,但是因为有接口调用,还是不行

相关推荐
倔强的石头_7 小时前
不想每次都从头解释:我用 Doubao-Seed-Evolving 做了一个「稿件接力站」
ai编程
咩咩啃树皮7 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
阳光是sunny7 小时前
LangGraph中的Reducer是什么
前端·人工智能·后端
触底反弹7 小时前
一文搞懂 Tailwind CSS 弹性布局:从原理到实战
前端·css·html
阳光是sunny7 小时前
从链到图:LangGraph 入门基础全解析
前端·人工智能·后端
小林ixn8 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
REDcker8 小时前
显示分辨率标准对照详解
前端·网络·分辨率·显示·屏幕
এ慕ོ冬℘゜8 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
武子康9 小时前
Search Console Platform Properties 扩大 SEO 资产边界:从 Page Ranking 到 Topic Coverage(5 类误读边界 + 3 表数据层设计)
前端·人工智能·后端
大模型码小白9 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程