让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里,但是因为有接口调用,还是不行

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
1点东西2 天前
做了近两年的Agent开发,其实真正要学的就是这五件事
llm·agent·ai编程
七牛云行业应用2 天前
Qwen-Image-2.1 开源部署完整指南:Diffusers、ComfyUI 与推理服务
ai编程
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
福如意如我心意2 天前
TencentDB Agent Memory和其他开源memory
ai编程
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端