-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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
[system] Fix CssVarsProvider
theme mutation
#31148
Conversation
|
||
// scope is the deepest object in the tree, keys is the theme path keys | ||
scope[keys.slice(-1)[0]] = value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the part where the theme is mutated.
}, | ||
(keys) => keys[0] === 'vars', // skip 'vars/*' paths | ||
); | ||
|
||
return { css, vars }; | ||
return { css, vars, parsedTheme }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parsedTheme
is the new object which will make functions inside baseTheme work.
if (key === resolvedColorScheme) { | ||
mergedTheme = { | ||
...mergedTheme, | ||
...parsedScheme, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this override the mergedTheme
palette values? Isn't the result of parsedScheme
a object containing palette as the first key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should override. When you change the color scheme, you will get a new theme.palette.*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally must, mergedTheme
should not have a palette as a key because the palette is handled inside color schemes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if the original theme contains more values there, like functions in the MD theme, we will loose them again no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, this works but the functions need to be in all color schemes.
createCssVarsProvider({
theme: {
colorSchemes: {
light: {
palette: {
getContrastText: (...) => {},
},
},
dark: {
palette: {
getContrastText: (...) => {},
},
}
}
}
})
const theme = useTheme();
theme.getContrastText(...)
However, if the function is only declared in light colo scheme, theme.getContrastText
will be undefined when you toggle dark color scheme. Is this making sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally,
mergedTheme
should not have a palette as a key because the palette is handled inside color schemes.
I would then say we should scratch ideally :D The base theme cannot have the palette key, because it is auto generated by the CssVarsProvider
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will update my branch with this change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, please document this, it's easy to be overlooked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added.
Based no #31138, there is a problem when
baseTheme
provided tocreateCssVarsProvider
contains functions. Those functions are removed because of JSON.stringify to make the object fresh on every render (the logic insideCssVarsProvider
mutate the object, so we need to make sure that the object is new on every call, otherwise the multipleCssVarsProvider
on a single page would not work).There are 2 possible ways to fix this:
basedTheme
as a function that returns a new objectCssVarsProvider
to not mutate the objectIn this PR, I chose the 2nd option because it is safer. It guarantees that the object is new on every renders and developers do not need to be concerned about the theme they are passing.
Performance
From what I collect, there is no performance difference between before and after. Collected by capturing the time (in millisecond) that the logic used in each render (sample sizes are 5).
Before
After
Test
Added regression test to make sure that multiple instances of
<CssVarsProvider>
with different prefix works.