I was asked to analyze the current application state management and optimization of re-renders. This issue is meant to be a discussion around the topic instead of a "let's do that now" solution. The reason why I want to discuss the issue before implementing it is because:
I miss the context: this is my first contribution to the project and I could completely miss the context of the real uses cases and problems.
This is a static analysis: the issue I want to discuss does not come from analyzing complex use cases nor from some users reporting a problem.
The current situation offers a great DX: I will discuss it later, but the current solution offers a great UX even if rerendering the whole app could sound suboptimal.
The theme can be switched by simply toggling the dark class in the DOM, but the current ThemeContextProvider also forces the whole component tree to re-render.
You can check that this would work since to switch the light/dark theme you only need to add/remove the dark class from the html DOM element, no need for any React Context around the whole application.
Devil's advocate
Why the optimization proposed in this issue should not be implemented?
It could not be a problem at all: as I said at the beginning, this issue is not the result of analyzing a problem, but more the result of an external and static analysis.
The current UX is good: even if the whole render tree rerenders when the theme changes, and even if this action would take (for instance) 1 second (that's a lot), it is the result of an explicit users' action. That means that the users expect that something changes (and potentially requires some time) when they directly change something that impacts the whole application!
The current ThemeProvider encapsulates the theme management: this eases the future refactor, and that's a really good thing! If in six months we need to migrate the theme management away from Tailwind, we only need to change the ThemeProvider and everything propagates to the whole application.
Reactivity to its best: the current ThemeProvider not only encapsulates all the theme management but also ensures the component tree is re-rendered when something with such a broad scope (the theme impacts everything) changes. Again, if the theme will be managed in a different way in the future, this is great!
Simulating themes is easy: If in the future we need to write component tests in Vitest/Cypress or stories in Storybook, etc. the ThemeProvider allows simulating all the theme options in a while, offering the best possible DX.
Conclusion
My two cents: I would keep the ThemeProvider as is, but I'd like to know what you think about the topic 😊
Notes
I did not use any of the existing templates because this issue is not a Bug report, nor a Feature request, nor a Security vulnerability.
I was asked to analyze the current application state management and optimization of re-renders. This issue is meant to be a discussion around the topic instead of a "let's do that now" solution. The reason why I want to discuss the issue before implementing it is because:
I miss the context: this is my first contribution to the project and I could completely miss the context of the real uses cases and problems.
This is a static analysis: the issue I want to discuss does not come from analyzing complex use cases nor from some users reporting a problem.
The current situation offers a great DX: I will discuss it later, but the current solution offers a great UX even if rerendering the whole app could sound suboptimal.
Current situation
The whole light/dark theme is based on the Tailwind-related class (see Toggling dark mode manually and https://github.com/paritytech/contracts-ui/blob/66a276e314ee5c2da85277b7a3eaed7a9667f9aa/tailwind.config.cjs#L6 ) and the
ThemeContextProvider
is used at the top of the application tree https://github.com/paritytech/contracts-ui/blob/66a276e314ee5c2da85277b7a3eaed7a9667f9aa/src/ui/components/App.tsx#L15.The theme can be switched by simply toggling the
dark
class in the DOM, but the currentThemeContextProvider
also forces the whole component tree to re-render.To Reproduce Steps to reproduce the behavior:
As you can see, all the application is highlighted (with a cyan border) since everything is re-rendered.
(if you want to check it online, you can use one of the "Deploy Preview" of a PR, like the #476 one)
Possible solution
Move all the theme management directly to the
ThemeMode
component https://github.com/paritytech/contracts-ui/blob/66a276e314ee5c2da85277b7a3eaed7a9667f9aa/src/ui/components/settings/ThemeMode.tsx#L19 that's the only current direct consumer of the theme, and removing theThemeProvider
.You can check that this would work since to switch the light/dark theme you only need to add/remove the
dark
class from thehtml
DOM element, no need for any React Context around the whole application.Devil's advocate
Why the optimization proposed in this issue should not be implemented?
It could not be a problem at all: as I said at the beginning, this issue is not the result of analyzing a problem, but more the result of an external and static analysis.
The current UX is good: even if the whole render tree rerenders when the theme changes, and even if this action would take (for instance) 1 second (that's a lot), it is the result of an explicit users' action. That means that the users expect that something changes (and potentially requires some time) when they directly change something that impacts the whole application!
The current
ThemeProvider
encapsulates the theme management: this eases the future refactor, and that's a really good thing! If in six months we need to migrate the theme management away from Tailwind, we only need to change theThemeProvider
and everything propagates to the whole application.Reactivity to its best: the current
ThemeProvider
not only encapsulates all the theme management but also ensures the component tree is re-rendered when something with such a broad scope (the theme impacts everything) changes. Again, if the theme will be managed in a different way in the future, this is great!Simulating themes is easy: If in the future we need to write component tests in Vitest/Cypress or stories in Storybook, etc. the
ThemeProvider
allows simulating all the theme options in a while, offering the best possible DX.Conclusion
My two cents: I would keep the ThemeProvider as is, but I'd like to know what you think about the topic 😊
Notes
I did not use any of the existing templates because this issue is not a Bug report, nor a Feature request, nor a Security vulnerability.