I have a component Marker, which I don't want to rerender unless really needed.
So it's wrapped in a memo hook, but since one of the props is an anonymous function, then the Marker still rerenders every time it's parent rerenders.
Now, this would have a simple solution of just wrapping the passed in function prop in useCallback hook, but since the function also takes a parameter, then I'm bit stuck in finding a nice solution. Memoizing the passed in function in a parent component with useMemo also will not work because of that parameter.
const Map = () => {
...
...
return(
{markers.map(marker => {
<Marker {...props} onPress={() => selectMarker(marker.id)}
})
)
}
const Marker = (...props, onPress) => {
... memoized function that at some point calls onPress()
}
CodePudding user response:
The most simple solution for this is to pass all the required arguments from the Marker component itself. With this change, you can make the onPress
handler pure.
const Map = () => {
const handleMarkerPress = useCallback((markerId) => {
selectMarker(markerId);
}, []);
return(
{markers.map(marker => {
<Marker {...props} marker={marker} onPress={handleMarkerPress}
})
)
}
const Marker = (...props, marker, onPress) => {
return <div onClick={() => onPress(marker.id)}>...</div>;
}
CodePudding user response:
Try to use the useCallback hook in the parent component to create the onPress function, and pass the marker.id as an argument to the callback. This way, the function will only be recreated if the marker.id value changes, and the Marker component will not re-render unnecessarily.
Here's how you could do this:
const Map = () => {
...
...
const selectMarker = useCallback((id) => {
// do something with the marker id
}, []);
return(
{markers.map(marker => {
<Marker {...props} onPress={() => selectMarker(marker.id)}
})
)
}
const Marker = ({ onPress }) => {
...
...
// call onPress when necessary
onPress();
}
The useCallback hook will return a memoized version of the selectMarker function that only changes if the values in the dependency array (in this case, an empty array) change. Since the selectMarker function is being passed as a prop to the Marker component, the Marker component will only re-render if the selectMarker function changes, which will only happen if the marker.id value changes.