question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

CSS styles duplication when using computed class names

See original GitHub issue
  • The issue is present in the latest release.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

When creating CSS classes dependents on passed props values, the styles are duplicated when the component refreshes.

Expected Behavior 🤔

The styles should properly be updated, removing any duplicates and unused by previous calls to makeStyles.

Steps to Reproduce 🕹

See provided sandbox

Declaring styles like this will create duplicates every time the component using the styles refresh :

const useStyles = makeStyles((theme) => ({
  testElement: ({ index, bgColor }) => ({
    [`& div:nth-child(${index})`]: {
      backgroundColor: bgColor
    },
    [`& div:not(:nth-child(${index}))`]: {
      backgroundColor: theme.palette.common.white
    }
  })
}));

Context 🔦

I noticed this behavior when debugging some styles I use in a project to render striped tables. The class renders custom striped tables given certain parameters.

Actual rules being applied
/**
 * Make table rows alternate in color. By default, every even row will have an alternate color.
 * 
 * Usage : 
 * 
 *   const useStyles = makeStyles(theme => ({
 * 
 *     table: {
 *       ...themedTableRows(theme(theme)
 *     }
 * 
 *   }));
 * 
 * 
 * Ex:  themedTableRows(theme, 1, 0)     // defaults
 *         - row
 *         - alternate row
 *         - row
 *         - alternate row
 * 
 * Ex:  themedTableRows(theme, 2)
 *         - row
 *         - row
 *         - alternate row
 *         - alternate row
 *         - row
 *         - row
 *         - alternate row
 *         - alternate row
 * 
 * Ex:  themedTableRows(theme, 3, 1)
 *         - row  (skipped)
 *         - row  (skipped)
 *         - row  (skipped)
 *         - row
 *         - row
 *         - row
 *         - alternate row
 *         - alternate row
 *         - alternate row
 *         - row
 *         - row
 *         - row
 *         - alternate row
 *         - alternate row
 *         - alternate row
 * 
 * @param {Object} theme          Material UI palette
 * @param {Number} groupSize      the number of rows to alternate
 * @param {Number} offset         skip the number of first groups
 * @return {Object}               classes to extend a rule with
 */
export const themedTableRows = (theme, groupSize = 1, offset = 0) => ({
   [groupSize < 2 ? '&:nth-of-type(even)' : Array.from({ length: groupSize }, (_, k) => `&:nth-child(${groupSize * 2}n+${k + groupSize + 1 + (offset * groupSize)})`).join(',')]: {
      backgroundColor: theme.palette.type === 'dark' ? darken(theme.palette.action.hover, 0.5) : lighten(theme.palette.action.hover, 0.4),
   },
   '&.Mui-selected': {
      backgroundColor: theme.palette.type === 'dark' ? darken(theme.palette.secondary.dark, 0.7) : lighten(theme.palette.secondary.light, 0.6),
   },
   [groupSize < 2 ? '&.Mui-selected:nth-of-type(even)' : Array.from({ length: groupSize }, (_, k) => `&.Mui-selected:nth-child(${groupSize * 2}n+${k + groupSize + 1 + (offset * groupSize)})`).join(',')]: {
      backgroundColor: theme.palette.type === 'dark' ? darken(theme.palette.secondary.dark, 0.65) : lighten(theme.palette.secondary.light, 0.4),
   }
});

I was adding :hover styles when I noticed the multiplication of overrides in the developer console.

Your Environment 🌎

`npx @material-ui/envinfo`
 System:
    OS: Linux 5.4 Ubuntu 20.04.1 LTS (Focal Fossa)
  Binaries:
    Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
    Yarn: 1.22.10 - ~/.nvm/versions/node/v14.5.0/bin/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm
  Browsers:
    Chrome: 88.0.4324.96
    Firefox: 85.0
  npmPackages:
    @material-ui/core: ^4.11.3 => 4.11.3 
    @material-ui/lab: ^4.0.0-alpha.57 => 4.0.0-alpha.57 
    @material-ui/pickers: ^4.0.0-alpha.12 => 4.0.0-alpha.12 
    @material-ui/styles:  4.11.3 
    @material-ui/system:  4.11.3 
    @material-ui/types:  5.1.0 
    @material-ui/utils:  4.11.2 
    @types/react:  16.9.50 
    react: ^16.13.1 => 16.13.1 
    react-dom: ^16.13.1 => 16.13.1 

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
oliviertassinaricommented, Feb 2, 2021

@yanickrochon Not yet, we start moving iteratively. We are moving toward the styled() and sx API. https://next.material-ui.com/components/slider/#unstyled-slider gives more context (looking at the demos)

0reactions
oliviertassinaricommented, May 9, 2021

An update, we have now made enough progress with the new @material-ui/styled-engine package in v5 to move toward a progressive removal of the @material-ui/styles package (based on JSS). The current plan:

  • In v5.0.beta.0, this package will come standalone, in complete isolation from the rest.
  • In v5.0.0, this package will be soft deprecated, not promoted in the docs, nor very actively supported.
  • During v5, work on making the migration easier to the new style API (sx prop + styled() API). We might for instance, invest in the documentation for using react-jss that has more or less the same API. We could also invest in an adapter to restore the previous API but with emotion, not JSS.
  • In v6.0.0, this package will be discontinued (withStyles/makeStyles API).

This was made possible by the awesome work of @mnajdova.

Read more comments on GitHub >

github_iconTop Results From Across the Web

CSS styles duplication when using computed class names
When creating CSS classes dependents on passed props values, the styles are duplicated when the component refreshes. Expected Behavior. The ...
Read more >
Can a dynamic class be styled using CSS? - Stack Overflow
Yes it is possible just by using CSS only. Option #1 - Match by prefix value. Use CSS Class selector ^="class" which select...
Read more >
Reusing Styles - Tailwind CSS
Managing duplication and creating reusable abstractions. Tailwind encourages a utility-first workflow, where designs are implemented using only low-level ...
Read more >
Using dynamic styling information - Web APIs | MDN
In many cases, and where possible, it is best practice to dynamically manipulate classes via the className property since the ultimate ...
Read more >
How to customize - Material UI - MUI
These class names can't be used as CSS selectors because they are unstable. Overriding styles with class names. If you want to override...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found