hairbo
hairbo

Reputation: 3153

Any cost to using `makeStyles` in a component that will be iterated (like a list item)?

I've got a component that's only ever going to be rendered as part of a list. Let's call it MyListItem. The easiest thing from a coding perspective is to localize the const useStyles = makeStyles(...) right inside MyListItem. But in that case, if there are 100 list items, then I'm potentially invoking useStyles 100 times.

Normally, I'd just say screw it and put the useStyles in the parent (e.g. MyList) and then pass classes down to MyListItem. That way, useStyles is only computed once, rather than 100 times.

However, MyListItem could get invoked by more than 1 parent (e.g. MyListOne, MyListTwo). That means that any parent that wants to invoke MyListItem needs to contain the styles for MyListItem, which is less than ideal.

So here's the question: is Material-UI smart at all about detecting that the same useStyles is being invoked again and again? Will it really write out 100 versions of those styles, or will it collapse all those down at runtime? My guess is the answer is "no", but I figured it was worth asking.

Thanks!

Upvotes: 2

Views: 726

Answers (1)

Ryan Cogswell
Ryan Cogswell

Reputation: 81026

Material-UI is definitely smart in this regard. If it wasn't, you would have the same problem with Material-UI's components such as ListItem. So long as makeStyles is being called at the top-level (which is the typical pattern) such that you are always using the exact same useStyles function, you are fine. A component that uses styles has more overhead than one that doesn't, but it won't duplicate the styles in the DOM.

The smarts in the library can be found here: https://github.com/mui-org/material-ui/blob/v4.9.13/packages/material-ui-styles/src/makeStyles/makeStyles.js#L56

let sheetManager = multiKeyStore.get(stylesOptions.sheetsManager, stylesCreator, theme);

This is the cache lookup for a particular style sheet. stylesOptions.sheetsManager will always be the same unless you are customizing it (very uncommon) for part of your component hierarchy using StylesProvider. stylesCreator is the argument to makeStyles -- i.e. the declaration of your styles. So for the same makeStyles call and the same theme, it will find the same styles and avoid re-generating them.

You can easily verify this is all working as intended by looking at the <style> elements in the <head> of your document via developer tools. The image below is from this page which is a sandbox for this other StackOverflow answer.

styles in head

You can see in the image style elements for the different Material-UI components used in the page (e.g. MuiSvgIcon, MuiListItem, etc.). You can also see one generated from makeStyles and one generated from withStyles. The withStyles case is similar to what you are describing -- it is styles for a ListItem component that is used multiple times in the page, but the styles only occur once in the document.

Upvotes: 1

Related Questions