const renderItem = useCallback(
({ item: { node } }) => {
const slug = node.slug;
const handlePress = () => {
push('SignedOutAssetScreen', { assetSlug: slug });
};
return <MarketCell onPress={handlePress} key={node.uuid} asset={node} />;
},
[push],
);
MarketCell is a memoized functional component - const MarketCell = memo((props) => ...);
Will MarketCell have re-renders or memo cache invalidations given its props?
The answer is yes
Why?
Because handlePress
is unstable. A function defined inside the renderItem's useCallback will be recreated everytime renderItem is called.
This recreation causes memo's cache to be invalidated.
How do we solve this problem?
Good thing you asked. XD
To answer the question I want to argue that it is a good practice to avoid defining unmemoized inlined functions when your useCallback needs to return a component that consumes that callback.
So for our case we can wrap the MarketCell component in another component so we can make sure of useCallback for the onPress callback:
const Item = memo(
({ asset }: { asset: MarketCellProps['asset'] & { slug: string } }) => {
const slug = asset.slug;
const { push } = useStackNavigation();
const handlePress = useCallback(() => {
push('SignedOutAssetScreen', { assetSlug: slug });
}, [slug, push]);
return <MarketCell onPress={handlePress} asset={asset} />;
},
);
changing the renderItem to:
const renderItem = useCallback(({ item: { node } }) => {
return <Item key={node.uuid} asset={node} />;
}, []);