If I identify a performance issue and want to memoize my components that use prop getters (like getItemProps), the prop getters are breaking memoization:
function Item({isHighlighted, getItemProps, item, index}) {
return (
<li
style={isHighlighted ? {backgroundColor: '#bde4ff'} : {}}
key={`${item}${index}`}
{...getItemProps({item, index})}
>
{item}
</li>
)
}
Item = React.memo(Item)
https://codesandbox.io/s/usecombobox-usage-1fs67?file=/src/index.js:431-454
If you pull up the React DevTools and run a profile, you'll observe that Items are getting re-rendered because getItemProps changed:

The solution should be pretty straightforward. Simply apply useCallback to all prop getters and action functions. So long as all dependencies are included (is eslint-plugin-react-hooks installed on this repo?) then it should be a patch version update.
To be clear, all of these should be memoized via useCallback:
Could probably use the same treatment in all the hooks:
Note, personally I wouldn't do the useCallback call in the code I linked
I would do it like this:
const getItemProps = React.useCallback(({
item,
index,
refKey = 'ref',
ref,
onMouseMove,
onClick,
onPress,
...rest
} = {}) => {
// ... contents of the file
}, [/* whatever the deps are goes here */])
Actually, I just realized that this line will break memoization for getItemProps specifically:
On every highlightedIndex change, all the Item components will get re-rendered because getItemProps will be new even though the props returned won't actually change for any but two items (the old highlighted one and the new highlighted one).
This can be side-stepped via useRef so we only reference the .current version of the highlightedIndex.
Also, this will break memoization of all items when items changes:
We could require that people pass the index to avoid this. That's what the Downshift component did (and it didn't need users to pass the items at all).
I'm going to go ahead and work on this. And I'm going to live stream it! https://youtu.be/UG3B5wjPuG0
Got it done! :) #1051
:tada: This issue has been resolved in version 5.4.0 :tada:
The release is available on:
npm package (@latest dist-tag)Your semantic-release bot :package::rocket:
Thanks!