news 2026/10/13 2:56:20

同一个 React Bug,我分别丢给了 DeepSeek、豆包和 GPT,差距比想象中大

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
同一个 React Bug,我分别丢给了 DeepSeek、豆包和 GPT,差距比想象中大

现在很多前端开发遇到 Bug,第一反应已经不是先去 Stack Overflow,也不是翻半天官方文档,而是直接把代码丢给 AI。

但问题也随之出现了:

明明都是 AI,为什么有时候一个模型能直接指出问题,另一个模型却会给你改一大堆代码,最后 Bug 还在?

这次就拿一个 React 开发里非常常见、而且特别容易被 AI “带跑偏”的问题,做一次同题模拟对比。

为了避免把不同版本、不同时间的模型表现写死,下面主要比较 DeepSeek、豆包和 GPT 在这类问题中的典型分析路径和解决思路,不把它当成绝对排名。


一、先看这个 React Bug

假设页面里有这样一段代码:

import React, { useEffect, useState } from "react"; export default function UserList() { const [users, setUsers] = useState([]); const [keyword, setKeyword] = useState(""); const params = { keyword, page: 1 }; useEffect(() => { fetch("/api/users?" + new URLSearchParams(params)) .then(res => res.json()) .then(data => { setUsers(data.list); }); }, [params]); return ( <div> <input value={keyword} onChange={e => setKeyword(e.target.value)} placeholder="搜索用户" /> {users.map(user => ( <div key={user.id}>{user.name}</div> ))} </div> ); }

乍一看,好像没什么问题。

逻辑也非常简单:

用户输入关键词 →keyword改变 → 请求接口 → 更新列表。

但实际运行以后,你可能会发现一个很离谱的现象:

接口一直请求。

哪怕用户什么都没操作,Network 里也可能连续出现请求。

如果接口响应比较快,甚至有机会直接把后端接口刷爆。


二、问题到底出在哪?

真正的问题其实就在这里:

const params = { keyword, page: 1 };

以及:

useEffect(() => { // ... }, [params]);

很多刚开始写 React 的开发者第一眼并不会意识到问题。

因为从人的角度看:

{ keyword: "", page: 1 }

和下一次渲染得到的:

{ keyword: "", page: 1 }

内容明明完全一样。

但 React 在判断依赖是否变化的时候,并不会帮你做对象内容的深度比较。

每次组件重新渲染时:

const params = { keyword, page: 1 };

都会创建一个新的对象引用。

也就是说:

{} !== {}

所以 React 会认为:

params 又变了。

于是整个过程变成:

组件渲染 ↓ 创建新的 params ↓ useEffect 发现 params 变化 ↓ 请求接口 ↓ setUsers ↓ 组件重新渲染 ↓ 又创建新的 params ↓ useEffect 再执行 ↓ 继续请求

这才是真正的根因。


三、把这个问题交给不同 AI,会发生什么?

这里才是我觉得比较有意思的地方。

因为这种 Bug 本身并不难。

真正能拉开体验差距的,往往不是:

AI 知不知道 useEffect。

而是:

AI 能不能迅速判断“哪一行代码才是真正的根因”。


四、DeepSeek:答案通常比较直接

如果把整段代码和“为什么接口一直请求”这个问题交给 DeepSeek,比较容易得到类似这样的分析:

params是一个对象,每次组件重新渲染都会创建新的引用,而useEffect依赖了params,因此 React 会认为依赖发生变化,导致 Effect 重复执行。

然后一般会给出几个解决方案。

例如直接修改依赖:

useEffect(() => { const params = { keyword, page: 1 }; fetch("/api/users?" + new URLSearchParams(params)) .then(res => res.json()) .then(data => { setUsers(data.list); }); }, [keyword]);

这个答案其实已经能解决问题了。

对于这种单文件、问题明确、上下文比较少的 Bug,DeepSeek 的表现通常已经完全够用。

而且它的优势很明显:

中文解释比较自然。

对于国内开发者来说,直接把报错、代码和需求一起扔进去,使用门槛很低。


五、豆包:解释会更偏“教学型”

豆包面对这种问题时,一个比较明显的特点是:

它往往会把问题拆得更细。

比如不仅告诉你:

params 每次渲染都会重新创建。

还可能顺便解释:

  • 什么叫引用类型
  • useEffect 怎么比较依赖
  • 为什么数组和对象容易触发类似问题
  • useMemo是干什么的
  • 为什么不能随便把对象放进依赖数组

例如可能给出这样的改法:

const params = useMemo(() => { return { keyword, page: 1 }; }, [keyword]);

然后:

useEffect(() => { fetch("/api/users?" + new URLSearchParams(params)) .then(res => res.json()) .then(data => setUsers(data.list)); }, [params]);

这同样是正确方案。

对于刚接触 React 的开发者来说,这种回答其实挺舒服。

因为它不是只告诉你:

“改这里。”

而是会解释:

“为什么要改这里。”


六、GPT 的区别,往往不是“知道答案”

再看 GPT。

如果只是问:

为什么这个 useEffect 会无限请求?

其实三个模型都有很大概率答出来。

所以真正值得看的,并不是这一道题谁会做。

而是继续往下追问:

这个项目实际开发中应该怎么改?

这时候答案开始出现差异。

比较成熟的分析通常不会急着告诉你:

useMemo

而是先判断:

这个 params 有必要存在吗?

因为从当前代码看:

const params = { keyword, page: 1 };

只是为了发请求。

那最简单的方案其实不是增加一个useMemo。

而是直接把真正影响请求的状态作为依赖:

useEffect(() => { const searchParams = new URLSearchParams({ keyword, page: "1" }); fetch(`/api/users?${searchParams}`) .then(res => res.json()) .then(data => { setUsers(data.list); }); }, [keyword]);

反而更简单。

这也是我觉得 AI 编程里一个很容易被忽略的问题:

能修好 Bug,不等于修改方案就是最合理的。


七、为什么“疯狂 useMemo”不一定是好答案?

看到对象引用变化以后,很多人会下意识写:

const params = useMemo(() => ({ keyword, page: 1 }), [keyword]);

技术上当然没问题。

但如果整个项目里一碰到对象就useMemo,代码很快就会变成:

const params = useMemo(...) const options = useMemo(...) const config = useMemo(...) const filter = useMemo(...)

最后组件里到处都是缓存。

这其实属于:

为了 Hooks 而 Hooks。

真正应该考虑的是:

这个对象是不是一定需要成为组件渲染阶段的变量?

如果只是某一个 Effect 内部使用,很多时候直接放进 Effect 里反而更加清晰。

这类“代码能不能继续简化”的判断,才是我认为现在不同 AI 编程体验真正容易拉开差距的地方。


八、再继续追问一步:其实还有隐藏问题

如果这是一段真实业务代码,我还会继续问 AI:

用户快速输入关键词怎么办?

比如用户连续输入:

a ab abc abcd

那就可能瞬间发送四次请求。

甚至还可能出现:

abcd 的请求先回来 abc 的请求后回来

结果旧数据把新数据覆盖了。

这时候问题已经不再是一个简单的:

useEffect 无限循环。

而变成:

  • 是否需要防抖
  • 是否需要取消旧请求
  • 如何避免竞态
  • loading 状态怎么处理
  • 请求失败怎么处理
  • 组件卸载以后是否还需要更新状态

真正用于生产环境的代码,可能会继续演进成:

useEffect(() => { const controller = new AbortController(); const timer = setTimeout(async () => { try { const searchParams = new URLSearchParams({ keyword, page: "1" }); const response = await fetch( `/api/users?${searchParams}`, { signal: controller.signal } ); const data = await response.json(); setUsers(data.list); } catch (error) { if (error.name !== "AbortError") { console.error(error); } } }, 300); return () => { clearTimeout(timer); controller.abort(); }; }, [keyword]);

你会发现:

最开始明明只是一个:

“为什么接口一直请求?”

最后其实可以延伸出完整的前端请求设计问题。


九、这才是我现在判断 AI 编程能力的方法

以前大家喜欢问:

哪个 AI 写代码最强?

但我现在越来越觉得,这个问题本身就太宽泛了。

因为如果只是:

写一个冒泡排序

或者:

写一个 React TodoList

现在很多模型都能完成。

真正应该测试的是:

第一,能不能找到根因

不是看到报错就开始改代码。

第二,能不能减少无意义修改

一个 Bug 最怕 AI 一次改十几个文件。

最后:

原来的问题没解决,又创造三个新问题。

第三,能不能理解真实项目环境

Demo 和真实业务完全是两回事。

真实项目还有:

  • 状态管理
  • 权限
  • 接口封装
  • TypeScript
  • ESLint
  • 路由
  • 请求缓存
  • 历史代码
  • 团队规范

第四,能不能继续往下发现问题

优秀的 AI 不应该只回答:

“这一行错了。”

而应该能进一步提醒你:

即使修改这一行,当前请求逻辑还有竞态风险。

这种能力在真正开发项目时,价值要高很多。


十、DeepSeek、豆包和 GPT,到底怎么选?

如果只是这一个 React Bug,我觉得完全没必要神化任何模型。

DeepSeek 能解决。

豆包也能解决。

GPT 同样能解决。

真正的区别,往往会随着任务复杂度增加才逐渐出现。

如果你的使用场景只是:

  • 看报错
  • 写 SQL
  • 查 API
  • 写一个函数
  • 解释代码

国内 AI 对很多开发者来说已经非常够用了。

但如果开始进入:

  • 大段代码分析
  • 连续 Debug
  • 多轮修改
  • 复杂业务逻辑
  • 项目级重构
  • 多文件上下文
  • 长时间协作开发

这时候才更值得认真比较不同模型。

我自己比较建议的是:不要一上来就纠结“谁最强”,而是把自己平时最真实的代码丢进去跑几天。

尤其是一直在用 DeepSeek、豆包,但还没有认真体验过 GPT 的开发者,实际拿同一个项目对比一次,感受会比看各种模型跑分直观得多。

这类东西没必要跟风。

能不能真正提高自己的开发效率,才是最重要的。


最后

这次这个 React Bug 本身其实很简单。

真正让我觉得有意思的,反而是一个变化:

以前程序员遇到 Bug,会搜索“这个问题怎么解决”;现在越来越多的人开始思考“这个问题应该交给哪个 AI 解决”。

而下一阶段,真正拉开效率差距的可能也不是:

你有没有使用 AI。

而是:

你能不能让 AI 真正理解你的项目,而不是只会让它生成几段看起来能运行的代码。

下一篇我准备继续拿一个更接近真实项目的问题测试:

“同一个 Spring Boot 接口响应变慢的问题,DeepSeek、豆包和 GPT 谁能真正定位到原因?”

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 2:56:19

Git连接GitHub超时443报错排查与修复全指南

Failed to connect to github.com port 443 after 21080 ms: Couldnt connect to——如果你在git pull或git clone时看到这样一行报错&#xff0c;恭喜你&#xff0c;踩中了Git使用频率最高的网络故障之一。这句话我这些年看了不下几百遍&#xff0c;自己也排查过从路由到防火墙…

作者头像 李华
网站建设 2026/10/13 2:52:07

数字人源码包实战指南:从环境搭建到口型驱动参数调优

简介&#xff1a;面向数字人技术研究者与小程序开发者&#xff0c;这是一份基于微信小程序实现的数字人源码包&#xff0c;涵盖数字人界面展示、交互逻辑与视觉资源&#xff0c;可帮助读者从零理解数字人在移动端的搭建思路&#xff0c;也便于后续二次开发。包内共129个文件&am…

作者头像 李华
网站建设 2026/10/13 2:52:06

技术人跨界农业5年:养殖数字化与物联网实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华