Skip to content

Performance: Update usage of stateless, functional components to class-based components when event handlers are used #607

Closed
@jeffcarbs

Description

@jeffcarbs

See below for original conversation regarding "RFC: Memoize event handlers in stateless, functional components". These are the TODOs that came out of the discussion.

Functional components that need to be turned into a class (Found via grep: const handle):

Other places where functions are created within render (Found via grep: const on[A-Z]):

There may be others so feel free to update this list!


Original discussion below regarding "RFC: Memoize event handlers in stateless, functional components"


Most of the conversation around this is in reference to actual components, not stateless functions. I've googled around a bit and the closest thing I've found to a discussion on this topic is: airbnb/javascript#784. This is also more of a general React question for you guys. I've run into this in my projects and haven't really settled on a great way to handle it.


I think using stateless, functional components is ideal and something we should strive for. However, initializing new arrays or functions inside a render (which we do) is considered an anti-pattern for performance reasons. Consider the DropdownItem component (pasting a simplified version here):

function DropdownItem(props) {
  const { value } = props

  const handleClick = (e) => {
    if (onClick) onClick(e, value)
  }

  return (
    <ElementType {...rest} className={classes} onClick={handleClick}>
      {/** content */}
    </ElementType>
  )
}

In this case, handleClick will be a new function each time this function is called so the props for the underlying element are changing.

One idea to solve this: Doesn't work, see below.

const handleClick = _.memoize((props) => (e) => {
  const { onClick, value } = props
  if (onClick) onClick(e, value)
})

function DropdownItem(props) {
  return (
    <ElementType {...rest} className={classes} onClick={handleClick(props)}>
      {/** content */}
    </ElementType>
  )
}

This would mean that a new function would be created any time the props changed but that would be way less frequent than on every single render. Trying to get more granular (e.g. using onClick as a memoization key) would probably lead to hidden gotchas.

This actually doesn't work since props will be a new object each time so the memoization comparison won't work.


Definitely open to other ideas here!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions