Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React hook dependent functions as props

After reading through the intro to hooks I have an immediate feeling that it has a performance problem with passing function props.

Consider the following class component, where the function reference is a bound function, so no re-renders happen because of it.

import React from 'react';

class Example extends React.Component {
  state = { count: 0 }

  onIncrementClicked = () => setState({ count: this.state.count + 1 })

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={this.onIncrementClicked}>
          Click me
        </button>
      </div>
    );
  }
}

Now compare it to the hooks-version where we pass a new function on each render to the button. If an <Example /> component renders, there's no way of avoiding the re-rendering of it's <button /> child.

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

I know it's a small example, but consider a bigger app where many callbacks are passed around that depend on hooks. How could this be optimised?

How would I avoid re-rendering everything that takes a function prop, that depends on a hook?

like image 551
Balázs Édes Avatar asked Aug 28 '26 03:08

Balázs Édes


1 Answers

You can use useCallback to ensure that event handler doesn't change between renders with the same count value:

const handleClick = useCallback(
  () => {
    setCount(count + 1)
  },
  [count],
);

For better optimisation you can store count value as an attribute of the button so you don't need access to this variable inside event handler:

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);
  const handleClick = useCallback(
    (e) => setCount(parseInt(e.target.getAttribute('data-count')) + 1),
    []
  );

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick} data-count={count}>
        Click me
      </button>
    </div>
  );
}

Also check https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render

like image 101
UjinT34 Avatar answered Aug 31 '26 06:08

UjinT34



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!