现代 React 应用卡顿的主要原因是什么?组件库 vs 重渲染机制 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
SonicKang
V2EX    React

现代 React 应用卡顿的主要原因是什么?组件库 vs 重渲染机制

  •  
  •   SonicKang 1 天前 2649 次点击

    最近在优化一个中大型 React 项目,遇到了一些性能问题,想请教下各位的经验。 背景:

    React 19 + TypeScript 使用了某主流 UI 组件库(Ant Design) 页面复杂度中等,有表格、表单、图表等

    问题: 应用在某些场景下会有明显的卡顿感,比如:

    输入框打字有延迟 列表滚动不流畅 弹窗打开/关闭有掉帧

    我的疑问:

    组件库的问题?

    这些成熟的组件库内部实现是否会带来性能开销? 是不是应该考虑换成更轻量的组件库,甚至自己写?

    React 重渲染机制?

    是不是没用好 memo / useMemo / useCallback? 状态管理不合理导致大范围重渲染?

    还是两者都有?

    33 条回复    2025-12-24 13:11:16 +08:00
    laikicka
        1
    laikicka  
       1 天前
    一般都是 全局状态滥用. 先用 React DevTools 看看吧.

    Ant Design 虽然性能比较差. 但是不太可能会有明显的卡顿感 (复杂度中等的情况下).
    joshua7v
        2
    joshua7v  
       1 天前   1
    不好说,可以用 react scan 检查一下,文字输入的时候是否触发很多组件重渲染了
    molvqingtai
        3
    molvqingtai  
       1 天前
    有试过 react compiler 吗,应该会修复一些性能问题
    Baymaxbowen
        4
    Baymaxbowen  
       1 天前 via iPhone
    重复渲染吧 打开调试工具看看
    ssshooter
        5
    ssshooter  
       1 天前
    是一个组件写了几千行还嵌套了复杂子组件没 Memo 吧,这个情况下随便一个 setState 都会跑完整 render 就会卡
    Linho1219
        6
    Linho1219  
       1 天前 via Android
    去 DevTools 性能面板录一段看一下什么步骤耗时最长。你这给的信息太少了,有可能是 JS 长时间占用主线程,也可能是 reflow 太多,或者读 DOM 导致频繁的样式重算等等;另外去无痕模式试试,也有可能是插件的锅
    okakuyang
        7
    okakuyang  
       1 天前
    牵一发动全身,改了一个 State 结果整个树渲染一遍。
    LandCruiser
        8
    LandCruiser  
       1 天前   1
    打字都卡就明显是数据的问题,可以从这个输入框绑定的变量入手排查。
    codehz
        9
    codehz  
       1 天前
    打字延迟这些你需要优化的可能是用 startTransition 等功能来降低更新重要性,但前提是你的代码支持这样的操作,不然可能会导致意外的问题(主要是由于全局状态管理的问题,大部分全局状态管理库所用的机制和并行渲染有本质上的不兼容,用 startTransition 并没有作用或者会导致数据出错)
    Lockroach
        10
    Lockroach  
       1 天前
    看 profile 定位,列表滚动卡顿可能是网络加载或者没有列表 item 复用等原因
    duan602728596
        11
    duan602728596  
       1 天前
    Ant Design 还没有差到动画都掉帧的情况。我猜就是项目里面的代码写的有问题。这种情况大部分就是下个库就开始写了,连库的文档都没看过,最严重的尤其就是 Form 。
    visper
        12
    visper  
       1 天前
    事件触发更新触发事件重复。
    TingLen
        13
    TingLen  
       1 天前
    打字有延迟的话,就去拍查下 onChange 之类的函数中,是不是做了什么监听改变某个状态值,然后又没有做防抖的处理。
    laved
        14
    laved  
       1 天前
    react19 新的 compiler 不是自动处理 memo 了吗 正常不需要自己手动加了把
    FakerLeung
        15
    FakerLeung  
       1 天前
    LobeChat 真的卡炸了,真的没办法优化了吗?
    yandif
        16
    yandif  
       1 天前   1
    可以试一下浏览器的性能面板,看看哪里的代码运行有性能瓶颈,然后进行优化
    https://developer.chrome.com/docs/devtools/performance?hl=zh-cn
    lizhenda
        17
    lizhenda  
       1 天前
    中大型 React 项目一旦没有强制规范很容易就变成这样
    anivie
        18
    anivie  
       1 天前
    @FakerLeung 这个项目真的第一次被 web 性能下限给吓哭了,点个设置卡了将近十秒钟才进去,我还以为是我部署错了,后面发现都是这样
    lpbname777
        19
    lpbname777  
       1 天前
    应该是代码写的有问题,拆分成最小单元再一步一步加
    liqiuqiu
        20
    liqiuqiu  
       1 天前
    performance 面板录制一下你的操作一看就知道怎么回事了
    Jannok
        21
    Jannok  
       1 天前
    卡成这样就不是组件库的问题,是写法的问题,尤其是 antd 这种,不至于这么差的
    sead
        22
    sead  
       1 天前
    Jynxio
        23
    Jynxio  
       1 天前
    React 自己的渲染机制决定的。

    React 内部用链表维护了一个树,用来映射 DOM 和更多东西(比如 Context 、Portal 、Fragment 等这些),你每次更新 React 的状态,React 都会从顶开始检查这棵树的每个节点,如果节点上的数据变了,那么就运行这个节点对应的组件(就是你写的 React 组件)。


    然后,你不写 Memo 、useMemo 的话,你的子组件就必然会跟着父组件的刷新而刷新,哪怕子组件的 Props 没变(为什么会这样?因为父组件传递给子组件的 Props 是一个对象,虽然这个对象的内容没变,但是对象自己不断的变)。

    于是,你就会发现,React App 一定有超多的冗余执行,这就是为什么 React 慢的其中一个原因。

    另外,React 那个树不是只遍历一遍的,他有时候还会回溯或者干脆从头再来。

    就是这么个渲染机制,导致 React 很难写丝滑。

    卡还是小问题,现在可以套 React Compiler ,问题是这个反复更新的渲染机制会让开发很复杂,比如 Effect 一多组件的行为就越难预测。

    我是一边用,一边忍,一边推荐给别人... 因为生态比别的 UI 库繁荣太多太多了。
    Jynxio
        24
    Jynxio  
       1 天前
    另外,Antd 自己本身性能就差,尤其是那个菜单组件。

    个人建议,Antd 过时了很久了,逃。
    cssTheGreatest
        25
    cssTheGreatest  
       1 天前
    接手旧的 B 端项目( react16+antDesign )时也遇过性能问题,体现在 form.setFieldsValue 的时候卡主线程
    zhengfan2016
        26
    zhengfan2016  
       1 天前
    @FakerLeung
    @anivie

    我不卡呀,自部署最新版本,我 pc 配置是 mba m3 和 amd 9600x ,两台设备都没遇到特别卡的问题
    zhengfan2016
        27
    zhengfan2016  
       1 天前
    @Jynxio #24 别说 antd 过时了,大部分大厂内部还在用呢,elementui 都一堆旧系统在用,打个响指全部变成 shadcn 可能吗,除非你这辈子只去小而美,否则逃不掉的
    Jynxio
        28
    Jynxio  
       1 天前
    @zhengfan2016

    同意,然后我会这样做「旧项目用了就用下去,新项目就直接用更现代的」。
    zhengfan2016
        29
    zhengfan2016  
       1 天前
    @Jynxio #28 这很难吧,用的前提是得说服领导,除非个人项目,我之前面试大厂外包碰到 tailwind 都不知道的面试官,还有一个女面试官面 react 的不知道 react-hook-form ,当时费好大劲解释为什么不用 antd 用这个和 shadcn
    DICK23
        30
    DICK23  
       1 天前
    React 本身性能就是差,antd 更是拉中之拉,两个加一起,再加个实习生前端,要是再加个表格中嵌套表单的全量可编辑设计,那基本没救了
    linkopeneyes
        31
    linkopeneyes  
       11 小时 5 分钟前
    输入框打字有延迟肯定不是组件库有问题,你应该看看自己在输入框数据变更的时候都做了什么导致大范围的重新渲染。
    列表滚动不流畅,是不是数据太多,上个虚拟滚动就能解决了。
    一般不卡的话不要使用 useMemo 这些 api ,更多是规范问题,少用 useEffect 能解决不少问题
    kid1412621
        32
    kid1412621  
       9 小时 59 分钟前
    @zhengfan2016 什么厂?连我这后端都知道……
    zhengfan2016
        33
    zhengfan2016  
       7 小时 19 分钟前
    @kid1412621 某中厂,深圳坂田地铁站附近
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2927 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 12:30 PVG 20:30 LAX 04:30 JFK 07:30
    Do have faith in what you're doing.
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-11940834-2', 'v2ex.com'); ga('send', 'pageview'); ga('send', 'event', 'Node', 'topic', 'react'); ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86