Performance penalty of creating handlers on every render with react-hooks

前端 未结 5 2136
野的像风
野的像风 2020-12-03 16:54

I\'m currently very amazed about the use cases of the new react hooks API and what you can possibly do with it.

A question that came up while experimenting was how e

5条回答
  •  盖世英雄少女心
    2020-12-03 17:36

    I did a simple test with the below example, which using 10k(and 100k) usingCallback hooks and re-rendering every 100ms. It seems that the number of useCallback could effect when it is really a lot. See the result below.

    Function component with 10k hooks:

    Each rendering took 8~12ms.

    Function component with 100k hooks:

    Each rendering took 25~80ms.

    Class component with 10k methods:

    Each rendering took 4~5ms.

    Class component with 100k methods:

    Each rendering took 4~6ms.

    I've tested with 1k example too. But the profile result looks almost same as the one with 10k.

    So the penalty was noticeable in my browser when my component using 100k hooks while class component didn't show noticeable difference. So I guess It should be fine as long as you don't have a component using more than 10k hooks. The number probably depends on client's runtime resource though.

    Test component code:

    import React, { useState, useCallback, useEffect } from 'react';
    
    const callbackCount = 10000
    const useCrazyCounter = () => {
      const callbacks = []
      const [count, setCount] = useState(0)
      for (let i = 1; i < callbackCount + 1; i++) {
        // eslint-disable-next-line
        callbacks.push(useCallback(() => {
          setCount(prev => prev + i)
          // eslint-disable-next-line
        }, []))
      }
      return [count, ...callbacks]
    }
    
    const Counter = () => {
      const [count, plusOne] = useCrazyCounter()
      useEffect(() => {
        const timer = setInterval(plusOne, 100)
        return () => {
          clearInterval(timer)
        }}
      , [])
      return 
    {count}
    } class ClassCounter extends React.Component { constructor() { super() this.state = { count: 0 } for (let i = 1; i < callbackCount; i++) { this['plus'+i] = () => { this.setState(prev => ({ count: prev.count + i })) } } } componentDidMount() { this.timer = setInterval(() => { this.plus1() }, 100) } componentWillUnmount() { clearInterval(this.timer) } render () { return
    {this.state.count}
    } } const App = () => { return (
    {/* */}
    ); } export default App;

提交回复
热议问题