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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
[styles] Memoize makeStyle result to avoid rerendering #25018
Comments
We are deprecating the withStyles and makeStyles APIs in v5. Moving to emotion and styled-components with a wrapper. |
Regarding the rerendering cost, the current approach should be fast enough for most of the cases. For instance, if I run a quick benchmark in v4 and v5, I get: It's improving. In the event you need high-performance updates, I would recommend looking into using CSS variables. We push it in #12827. |
I would understand if you don't want to investigate this, but I would appreciate a response to the problem I tried to describe, not argumentation with some benchmark that may not be relevant for the issue.
Obviously, if I have Does the v5 solution avoid the problem or not? E.g. Redux does the optimization that if the map-state-to-props function results in the same data (shallow equality), it does not render the component. As virtually every UI component is behind its "logical" wrapper, this avoids render of almost all components on any state change; the shallow-equality test on map-state-to-props result is OK for all components and helps to avoid potentially much more costly renders. We should have something similar for style classes. |
We don't plan to change the theme rendering tradeoff with the styled API ("wont fix"). Looking at emotion, it's worse in v5 compared to v4 as it rerenders even if the theme is not used: https://codesandbox.io/s/admiring-dhawan-77tmu?file=/src/App.tsx:0-610. I would imagine the same thing for styled-components. #12827 should allow the outcome you are looking for, by using CSS cascading, not React context cascading to update between the light and dark mode. |
Summary 馃挕
A common style of getting class names for
className
prop is the following pattern:The Material UI app is wrapped in
ThemeProvider
context. A component usesuseStyles
as follows:Changing theme object (via
setTheme
) causes that allmakeStyles
callbacks run with newtheme
, and it generates new set of classes used by application. The components are rerendered so that they read new class names inclasses
and React will then propagate the changes to browser DOM.It looks that
useStyles
hook causes component to render even if there is no real change in class content. Let's take the examplemakeStyles
above. If I can change e.g. a primary color in a theme, new run ofmakeStyles
will return the same as before:root: { padding: 8 }
. A component usinguseStyles
could stay the same, there is no need to create new class name and rerender the component.Proposal: At least some trivial memoizing should be added to
makeStyles
, so that iftheme
is changed, but a class returned bymakeStyles
has the same value, the class should stay the same; if all classes frommakeStyles
result are the same as before, a component usinguseStyles
should not rerender.Examples 馃寛
Changing e.g. primary color in theme causes new run
makeStyles
, but the values ofroot
andchild
are the same as before (shallow compare onroot
andchild
). A component using theseuseStyles
should not be rendered, the MUI internals should swallow this change of theme which has no impact on this component.Changing primary color in theme make
root
differ from previous run. Thechild
may stay the same. Theroot
class has changed, a component render must be triggered.Motivation 馃敠
I developed a quite complicated API visualizer with lot of rows, boxes, values, icons etc.; the DOM is really non-trivial. I provide a dark/light switcher. A use
makeStyles
/useStyles
in virtually every component. Changing the theme from light to dark or vice versa has direct impact on few components; almost allmakeStyles
use onlytheme.spacing
which I don't touch. Switching the theme causes that virtually all component must be recomputed, it's really slow in dev mode, and noticeable in prod mode.If there was even a trivial optimization in
makeStyles
/useStyles
(shallow compare on class objects), then changing of theme could be really fast, now it's lagging as whole application must be rendered again.The text was updated successfully, but these errors were encountered: