Reputation: 3081
I have implemented this component:
function CardList({
data = [],
isLoading = false,
ListHeaderComponent,
ListEmptyComponent,
...props
}) {
const keyExtractor = useCallback(({ id }) => id, []);
const renderItem = useCallback(
({ item, index }) => (
<Card
data={item}
onLayout={(event) => {
itemHeights.current[index] = event.nativeEvent.layout.height;
}}
/>
),
[]
);
const renderFooter = useCallback(() => {
if (!isLoading) return null;
return (
<View style={globalStyles.listFooter}>
<Loading />
</View>
);
}, [isLoading]);
return (
<FlatList
{...props}
data={data}
keyExtractor={keyExtractor}
renderItem={renderItem}
ListHeaderComponent={ListHeaderComponent}
ListFooterComponent={renderFooter()}
ListEmptyComponent={ListEmptyComponent}
/>
);
}
As my CardList component is heavy, I have tried to optimize it following these tips.
But, I think that instead of using useCallback
for renderFooter
, I should use useMemo
, in order to memoize the resulted JSX and not the method:
const ListFooterComponent = useMemo(() => {
if (!isLoading) return null;
return (
<View style={globalStyles.listFooter}>
<Loading />
</View>
);
}, [isLoading]);
Am I correct?
Upvotes: 2
Views: 4308
Reputation: 28654
In general useMemo
is used to cache the result of a calculation between re-renders; seems that is more appropriate for your case because you are calling renderFooter
and passing its result as props.
Note there is also a possibility to optimize rendering using useMemo
, it is highlighted in the docs:
function Parent({ a, b }) {
// Only re-rendered if `a` changes:
const child1 = useMemo(() => <Child1 a={a} />, [a]);
// Only re-rendered if `b` changes:
const child2 = useMemo(() => <Child2 b={b} />, [b]);
return (
<>
{child1}
{child2}
</>
)
}
The reason why it works here is probably due to the fact that when during a re-render, react sees reference to the same react element in the same place in component hierarchy, it skips re-rendering it. This happens here because by using useMemo
to create child1
and child2
elements, we ensure that the same element reference is returned on subsequent renders as long as its dependencies have not changed.
useCallback
lets you cache a function definition.
Upvotes: 3
Reputation: 82219
useMemo
is perfectly sensible here as it memoizes the result (the JSX). As you say, useCallback
memoizes the function not the result.
Upvotes: 0
Reputation: 1074228
"Should" is a matter of opinion, but you certainly can. React elements are fully reusable. It's not likely to make any real difference to your component, though, since creating the elements is fast and renderFooter
is just used immediately in a component that's already running (unlike keyExtractor
and renderItem
, which you're passing to FlatList
, so you want to make them stable where possible so FlatList
can optimize its re-rendering). But you certainly can do that.
Upvotes: 0