V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
cl903254852
V2EX  ›  程序员

关于 react-hooks 一个可能跟性能有关的疑问

  •  
  •   cl903254852 · 2020-05-30 10:28:55 +08:00 · 3598 次点击
    这是一个创建于 1668 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近从 class component 切换到 react hooks 写法.

    比如下面这个例子:

    
    function Demo(){
        const [count, setCount] = useState(0);
        
        useEffect(()=>{
        
        },[])
        
        const func_1 = () => { //... }
        const func_2 = () => { //... }
        const func_3 = () => { //... }
        // 这里还有 const 其他变量...
        
        return <div/>
    }
    

    我发现,只要状态改变,Demo 这个函数就会重新执行一次, 也就是说定义在 Demo 里的所有变量每次 render 时都会重新定义, 这样不会有性能问题吗?

    而且 Demo 这个函数中返回了组件 jsx,它不就是 class component 里的 render 方法吗? 相当于我这些定义的变量是在 render 方法里定义的?

    • 大家在写 react hooks 时,对于这些是怎么处理的?
    • 有没有其他会影响性能的地方?

    鄙人也是刚入手 react hooks , 望大家指点一二,Thanks♪(・ω・)ノ

    21 条回复    2020-05-30 22:00:29 +08:00
    CodingNaux
        1
    CodingNaux  
       2020-05-30 10:39:30 +08:00 via iPhone
    看文档
    lbw
        2
    lbw  
       2020-05-30 10:43:57 +08:00
    1. 示例代码的 Demo 函数就是函数式组件,那么在组件 props 变化或 hook 状态改变,必然要通过调用整个 Demo 函数来产生新的 vnode,进而更新 dom,因为函数式组件本身就是一个函数!!它只有通过重新调用才能产生新的副作用,而不像 class 可通过调用 render
    2. 对应的你说的因每次调用 Demo 而产生的性能问题,react 官方通过 hook 的第二个参数(即上文 useEffect 的空数组)来实现在每次 Demo 函数调用期间实现使用缓存,而不是每次都重新计算,这也是 hook 的特性之一
    3. 其他比如 useCallback useMemo 等 hook 均是通过第二个参数数组来申明 hook 的依赖,进而实现复用缓存
    4. class 中 render 起到的作用就是调用函数式组件的调用结果——产生新的 vnode,进而通过协调算法更新视图。class 组件和函数式组件的本质区别之一就是 class 自带生命周期和状态
    whe
        3
    whe  
       2020-05-30 10:44:36 +08:00   ❤️ 1
    useMemo & useCallback
    duan602728596
        4
    duan602728596  
       2020-05-30 10:48:40 +08:00 via iPhone
    可以用 useMemo 和 useCallback,让变量或者函数只在依赖变化时重新计算。
    性能的话,大部分项目还没有复杂到必须进行性能优化。
    CodingNaux
        5
    CodingNaux  
       2020-05-30 10:53:37 +08:00 via iPhone
    有些函数都没必要用 useCallback 包裹,丢在组件外面就可以了
    CodingNaux
        6
    CodingNaux  
       2020-05-30 10:55:12 +08:00 via iPhone
    有些简单计算没必要用 useMemo 包裹
    zhuangzhuang1988
        7
    zhuangzhuang1988  
       2020-05-30 10:58:05 +08:00
    react 就这样 引入 hook 心智负担变得更大了

    vue 相对好很多, 不过也有坑, 很容易组件就不响应式了
    pyplayer
        8
    pyplayer  
       2020-05-30 11:43:25 +08:00 via iPhone
    lancelock
        9
    lancelock  
       2020-05-30 11:47:31 +08:00 via iPhone
    最近也在写 hooks 。优点是很明显,但感觉并非完美方案
    zhuweiyou
        10
    zhuweiyou  
       2020-05-30 11:49:37 +08:00   ❤️ 1
    太小看 现代电脑 /手机了,一般的场景,还没到性能优化的地步。有这功夫还不如想想,怎么优化一下用户体验。
    fancy2020
        11
    fancy2020  
       2020-05-30 12:03:58 +08:00
    变量定义本身的性能消耗可以忽略不计的,如果你的变量定义依赖一个复杂运算的结果,那么这个运算可以用 useMemo 来缓存结果,在依赖不变的情况下不会重复执行计算过程。
    WeiShurong
        12
    WeiShurong  
       2020-05-30 12:30:32 +08:00
    楼上都说的很好了。补充一下,如果你真的很在乎 render 的次数,你可以使用 React.memo 包裹函数式组件,这样只有 prop 变更时,才会调用(和 shouldComponentUpdate 一样)
    joesonw
        13
    joesonw  
       2020-05-30 12:32:00 +08:00
    1. 有改变只会是 vdom 改变, 之后还要做 diff 的. 影响性能是在是忽略不计了.
    2. hook 本身有缓存机制, 善用. 例如回调用 useCallback 的话, 只在 dependency list 变化的情况下才会重新取值(取函数)
    love
        14
    love  
       2020-05-30 12:36:21 +08:00
    别说会重新执行函数了,更大的坑是小心别引用了旧变量。

    所以我觉得 vue 版 hooks 是更优设计
    seki
        15
    seki  
       2020-05-30 12:46:51 +08:00
    虚拟 dom 计算这一层是纯 js 的,一般来讲对性能影响不大。改变 dom 对性能的影响是更主要的

    其它的,在了解 hooks 之前先了解一下 function component 更好
    ChefIsAwesome
        16
    ChefIsAwesome  
       2020-05-30 13:02:30 +08:00
    有影响。大不大看你组件复杂不复杂。
    sucai
        17
    sucai  
       2020-05-30 14:04:34 +08:00
    在外面用 react.memo 包一下 Demo
    dcatfly
        18
    dcatfly  
       2020-05-30 14:19:43 +08:00
    建议先完整阅读一遍 react hooks 相关的文档,你说的这些问题文档都有解
    myCupOfTea
        19
    myCupOfTea  
       2020-05-30 14:22:42 +08:00
    有影响,不过不是太太太复杂的系统可以忽略不计,所以才有了 useRef useMemo useCallback
    limi58
        20
    limi58  
       2020-05-30 14:24:10 +08:00
    一般重复定义只是定义而已,性能消耗忽略不计,并没有复杂运算,如果有,useMemo useCallback 直接上场
    royzxq
        21
    royzxq  
       2020-05-30 22:00:29 +08:00
    合理利用 useMemo useCallback
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4011 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:13 · PVG 13:13 · LAX 21:13 · JFK 00:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.