Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
119
rated 0 times [  120] [ 1]  / answers: 1 / hits: 40448  / 6 Years ago, mon, november 5, 2018, 12:00:00

As said in docs, useCallback
Returns a memoized callback.


Pass an inline callback and an array of inputs. useCallback will return a memoized version of the callback that only changes if one of the inputs has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).


const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);

But how does it work and where is the best to use it in React?


P.S. I think visualisation with codepen example will help everyone to understand it better. Explained in docs.


More From » reactjs

 Answers
8

This is best used when you want to prevent unnecessary re-renders for better performance.


Compare these two ways of passing callbacks to child components taken from React Docs:


1. Arrow Function in Render


class Foo extends Component {
handleClick() {
console.log('Click happened');
}
render() {
return <Button onClick={() => this.handleClick()}>Click Me</Button>;
}
}

2. Bind in Constructor (ES2015)


class Foo extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click happened');
}
render() {
return <Button onClick={this.handleClick}>Click Me</Button>;
}
}

Assuming <Button> is implemented as a PureComponent, the first way will cause <Button> to re-render every time <Foo> re-renders because a new function is created in every render() call. In the second way, the handleClick method is only created once in <Foo>'s constructor and reused across renders.


If we translate both approaches to functional components using hooks, these are the equivalents (sort of):


1. Arrow Function in Render -> Un-memoized callback


function Foo() {
const handleClick = () => {
console.log('Click happened');
}
return <Button onClick={handleClick}>Click Me</Button>;
}

2. Bind in Constructor (ES2015) -> Memoized callbacks


function Foo() {
const memoizedHandleClick = useCallback(
() => console.log('Click happened'), [],
); // Tells React to memoize regardless of arguments.
return <Button onClick={memoizedHandleClick}>Click Me</Button>;
}

The first way creates callbacks on every call of the functional component but in the second way, React memoizes the callback function for you and the callback is not created multiple times.


Hence in the first case if Button is implemented using React.memo it will always re render (unless you have some custom comparison function) because the onClick prop is different each time, in the second case, it won't.


In most cases, it's fine to do the first way. As the React docs state:



Is it OK to use arrow functions in render methods? Generally speaking,
yes, it is OK, and it is often the easiest way to pass parameters to
callback functions.


If you do have performance issues, by all means, optimize!



[#53172] Wednesday, October 31, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
simone

Total Points: 558
Total Questions: 96
Total Answers: 99

Location: British Indian Ocean Territory
Member since Tue, Feb 22, 2022
2 Years ago
;