Bobolo
  • Home
  • Me

React

Function and Class components in React

6 Min Read

Tue Jul 02 2019

Written By Bobolo

I had this concern when I first started writing React hooks, wouldn't it be performance intensive for function components to recreate the closures inside each render?

The methods of class components are static and unchanging, so are class components a little better at this?

  • Create: What is the speed of creation under normal conditions?
  • Closure Complexity: Does the complexity of closures also affect the speed of creation?
  • In React : What is the performance of the two in a React environment?

A simple test.

//Create

const bench = require('benchmark')

const suite = new bench.Suite()

function myComp(i) {
  function foo() {
    return i + 1
  }
  return foo()
}

function staticFoo(i) {
  return i + 1
}

function myComp2(i) {
  return staticFoo(i)
}

suite
  .add('closure create', () => {
    myComp(Math.random())
  })
  .add('static', () => {
    myComp2(Math.random())
  })
  .on('cycle', evt => {
    console.log(String(evt.target))
  })
  .on('complete', function () {
    console.log('Fastest is ' + this.filter('fastest').map('name'))
  })
  .run()
closure create x 46,013,919 ops/sec ±1.55% (91 runs sampled)
static x 46,724,334 ops/sec ±0.97% (89 runs sampled)
Fastest is static

There is no doubt that static functions are a little faster, but the difference is so small that it is almost negligible in real-world scenarios. The documentation also mentions that Class itself has some additional overhead and is difficult to optimise, so this basically offsets the overhead of function creation

//Closure Complexity
const bench = require('benchmark')

const suite = new bench.Suite()

function myComp(i) {
  function foo() {
    return i + 1
  }
}

function myComp2(i) {
  function complexFoo() {
    console.log(i)
    let j
    for (j = 0; j < i; j++) {
      console.log(i + j)
    }
    for (; j > 0; j--) {
      console.log(i + j)
    }
    return i + 1
  }
}

suite
  .add('simple', () => {
    myComp(Math.random())
  })
  .add('complex', () => {
    myComp2(Math.random())
  })
  .on('cycle', evt => {
    console.log(String(evt.target))
  })
  .on('complete', function () {
    console.log('Fastest is ' + this.filter('fastest').map('name'))
  })
  .run()
simple x 45,947,495 ops/sec ±1.41% (87 runs sampled)
complex x 46,278,683 ops/sec ±1.33% (89 runs sampled)
Fastest is complex,simple

It has been tested that the complexity of closures does not basically affect the efficiency of their creation.

// React
const React = require('react')
const ReactDOM = require('react-dom/server.node')
const bench = require('benchmark')
process.env.NODE_ENV === 'production'

const suite = new bench.Suite()

function Func() {
  return React.createElement(
    'span',
    {
      onClick: () => {
        console.log('click')
      },
    },
    'children'
  )
}

class Cls extends React.Component {
  handleP() {
    console.log('click')
  }

  render() {
    return React.createElement('span', { onClick: this.handleP }, 'children')
  }
}

suite
  .add('function component', () => {
    ReactDOM.renderToString(React.createElement(Func))
  })
  .add('class component', () => {
    ReactDOM.renderToString(React.createElement(Cls))
  })
  .on('cycle', evt => {
    console.log(String(evt.target))
  })
  .on('complete', function () {
    console.log('Fastest is ' + this.filter('fastest').map('name'))
  })
  .run()
D:\home\workspace\playground>node class-vs-func.js
function component x 143,556 ops/sec ±8.58% (89 runs sampled)
class component x 143,543 ops/sec ±7.58% (86 runs sampled)Fastest is class component,function component

D:\home\workspace\playground>node class-vs-func.js
function component x 151,240 ops/sec ±1.84% (87 runs sampled)
class component x 150,126 ops/sec ±2.96% (81 runs sampled)
Fastest is function component,class component

D:\home\workspace\playground>node class-vs-func.js
function component x 132,336 ops/sec ±8.49% (86 runs sampled)
class component x 142,621 ops/sec ±2.95% (88 runs sampled)
Fastest is class component

D:\home\workspace\playground>node class-vs-func.js
function component x 145,461 ops/sec ±3.41% (86 runs sampled)
class component x 137,405 ops/sec ±6.83% (81 runs sampled)
Fastest is function component,class component

Currently, class components and function components are comparable in terms of efficiency for the same functionality

Conclusion

So it is safe to use Hook, except that we can still do some optimizations, such as

  • Extracting functions as static
  • Simplifying the complexity of components
  • Caching with React.memo/React.callback
Powered by Bobolo

Copyright © Bobolo Blog 2021