Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[styles] Dynamic makeStyles unexpected behavior #15511

Closed
2 tasks done
jmdsg opened this issue Apr 27, 2019 · 15 comments
Closed
2 tasks done

[styles] Dynamic makeStyles unexpected behavior #15511

jmdsg opened this issue Apr 27, 2019 · 15 comments
Labels
bug 🐛 Something doesn't work package: styles Specific to @mui/styles. Legacy package, @material-ui/styled-engine is taking over in v5.
Milestone

Comments

@jmdsg
Copy link

jmdsg commented Apr 27, 2019

  • This is not a v0.x issue.
  • I have searched the issues of this repository and believe that this is not a duplicate.

I have found some issues using makeStyles with dynamic styles (arrow functions) and i'm going to list them here since i think those may be related, and i feel that is unnecessary to create one issue per each of these points.

This issues are shown in this codesandbox MCVE https://codesandbox.io/s/lrwvw5lx6q.

  1. The class name of a dynamic style contains 2 classes, the first is the represents the static class (hence is empty) and the second the dynamic class (with the actual styles).
    This behavior may be the intended to allow the reference of a static class from a dynamic class but i don't think is working, at least not completely.
  2. Cannot mix or reference (with $) a static class (not using arrow function) from a dynamic class (using arrow).
  3. Using some complex classname (not sure exacly which ones cause this behavior) when the component is rerendered (by a state change for instance) the previous style is not removed and the style sheet gets polluted and starts to have duplicate classes.
  4. Cannot use a dynamic keyframe (using arrow function).
  5. Cannot use/reference a static keyframe (just as an object) from a dynamic class. This may be related to (2).
  6. And the last is more a question, i checked the code for makeStyles and i see that it does not depend on props, everytime useStyles is called and no matter if the props are the exacly the same the stylesheet is updated. Any reason for this?

Because when you call useStyles(props) with the same props or even using something like this:

const {
    height,
    width,
    ...rest
} = props;

// using only props that affect the styles generated
const memoizedStyleProps = useMemo(() => ({ height, width }), [height, width]);
const classes = useStyles(memoizedStyleProps);

Doesn't seem necessary to update the stylesheets.

Expected Behavior

  1. Just one class name per dynamic style, e.g. makeStyles-animate-10
  2. Be able to reference a static class from a dynamic class
  3. Be able to rerender the component with complex classes without ending up with duplicate css rules in the style sheet.
  4. Be able to use a key frame as a result of an arrow function.
  5. Be able to use a static key frame from a dynamic style.

Current Behavior

  1. Two class names per dynamic style, e.g. makeStyles-animate-4 makeStyles-animate-10
  2. Cannot reference a static class from a dynamic class. In the example shows index.js:26 Warning: [JSS] Could not find the referenced rule simple in makeStyles.
  3. Using a complex classname and rerendering the component causes the style sheet gets polluted
  4. Not able to use a key frame as a result of an arrow function.
  5. Not able to use a static key frame from a dynamic style. In the example shows index.js:26 Warning: [JSS] Referenced keyframes rule "rotate1" is not defined.

Steps to Reproduce

  1. Inspect any of the elements using a dynamic class name and it will have a two classnames for.
  2. In the example, if you change the definition of the class simple from simple: {} to simple: () => ({}) the title Hello CodeSandbox will have the expected green color.
  3. Click one of the buttons in the example multiple times and then either inspect the h2 containing You clicked X times! or checking the rules in the sandbox document.styleSheets there will be multiple rule definitions repeated.
  4. In the example the keyframe named rotate2 that is inside an arrow function is generated with empty body. The animation is not being applied.
  5. In the example the keyframe named rotate1 is generated correctly but it is not referenced. The animation is not being applied.

Your Environment

Tech Version
Material-UI v4.0.0-alpha.8 and v4.0.2
React 16.8.0
Browser Chrome: version 73.0.3683.103 (Build official) (64 bits)
TypeScript No

Not sure if all this points are really issues or some of them are not allowed and its behavior is undefined.

@oliviertassinari oliviertassinari self-assigned this Apr 28, 2019
@oliviertassinari
Copy link
Member

cc @kof

@oliviertassinari oliviertassinari added the package: styles Specific to @mui/styles. Legacy package, @material-ui/styled-engine is taking over in v5. label May 12, 2019
@oliviertassinari oliviertassinari removed their assignment May 27, 2019
@jmdsg
Copy link
Author

jmdsg commented Jun 16, 2019

Any news on this?

@joacub
Copy link

joacub commented Jul 1, 2019

Same here is called too many times unnecessary

@Fleuv
Copy link

Fleuv commented Oct 13, 2019

Encountered this problem as well.

I noticed that this problem only occurs when using a nested selector. So adding a separate class to the element the nested selector points at and adding the dynamic styling to that class should solve the problem.

In this code sandbox I debugged the problem:
https://codesandbox.io/s/styling-duplicates-on-state-change-0weti

Note: In my browser (FireFox) I had to close and open the inspector to see the affect, thus make sure you follow the debug instructions in the demo.

Conclusion

This doesn't work:

myParentElement: (props) => ({
  '& .myNestedElement': {
    // use props
  }
})

This does work:

myNestedElement: (props) => ({
  // use props
})

@warren-liang-exa
Copy link

warren-liang-exa commented Jan 31, 2020

Is there any update on this issue? Still getting more than one class when using props for adaptive styling.

@schnerd
Copy link

schnerd commented Feb 14, 2020

Also interested in item 6 – makeStyles shouldn't re-calculate and re-attach styles unless the props change.

I'd imagine it can be fixed with a small change like schnerd@21f98bd.

@oliviertassinari
Copy link
Member

These issues should have been solved in v5 thanks to #22342 and the new @material-ui/styled-engine package. You can play with it at: https://codesandbox.io/s/bold-goodall-2iltv?file=/src/App.tsx. By default, it wraps emotion.

@oliviertassinari oliviertassinari changed the title Dynamic makeStyles unexpected behavior [styles] Dynamic makeStyles unexpected behavior Nov 12, 2020
@oliviertassinari oliviertassinari added the bug 🐛 Something doesn't work label Nov 12, 2020
@wwahammy
Copy link

So, what's the work around on v4?

@ffjanhoeck
Copy link
Contributor

@oliviertassinari A workaround for v4 would be really awesome. We have huge application, which is using material-ui.
That means, when v5 gets released, we have to prepare 400 files before we can really update...

@oliviertassinari
Copy link
Member

@ffjanhoeck I would recommend trying react-jss out. The migration should be easy and they have a better handling of this problem. Also note that you don't need to migrate all the makeStyles and withStyles in v5, the module is still here.

@ffjanhoeck
Copy link
Contributor

ffjanhoeck commented Apr 15, 2021

@oliviertassinari Is the makeStyles in material-ui v4 not a react-jss wrapper?

Or do you mean by trying out react-jss, that I should directly use react-jss, without the makeStyles from material-ui ?

@oliviertassinari
Copy link
Member

@ffjanhoeck Material-UI v4 uses jss, not react-jss. My suggestion is to use react-jss

@oliviertassinari
Copy link
Member

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.

@maticrivo
Copy link

Hi @oliviertassinari
How do we change the usage of jss in favor of react-jss in v4 to solve this issue temporarily until we can upgrade to v5?

I couldn't find anything about it in the docs.

Thanks.

@ezbeazy
Copy link

ezbeazy commented Jul 27, 2024

@maticrivo this worked for me.

https://stackoverflow.com/questions/62902832/why-do-you-need-to-apply-the-two-generated-class-names-root-disabled-to-the

add to createStyles in makeStyles
disabled: { // Define any styles for the disabled state if needed },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work package: styles Specific to @mui/styles. Legacy package, @material-ui/styled-engine is taking over in v5.
Projects
None yet
Development

No branches or pull requests

10 participants