cssinjs / jss

JSS is an authoring tool for CSS which uses JavaScript as a host language.
https://cssinjs.org
MIT License
7.08k stars 399 forks source link

Style block un-renders when any param used - since v10.0 #1646

Open allpro opened 1 year ago

allpro commented 1 year ago

Expected behavior: Styles for a React component should remain rendered until component unmounts.

Describe the bug: When any param is used in a stylesheet, all the styles are immediately deleted after rendering. This issue exists in every v10.x version.

Reproduction: This bug can be seen in the sandbox demo provided by this package, with zero changes:

In the demo a theme prop is passed and used in the stylesheet, which is all it takes to trigger the bug. To see the issue:

  1. Inspect the H1 element
  2. In the Styles panel, click either of the <style> tags created by JSS
  3. The referenced style tag element is displayed
  4. Observe that the style tag is EMPTY - no style rules are rendered

Attached are 2 screenshots that illustrate the steps above, using the unaltered sandbox.

Versions (please complete the following information):

I tried multiple versions all the way back to v10.0.0 to try finding a version without the problem, but every version has it. I could not go back to v9.x because we use the createUseStyles hook in our app, which was added in v10.

Why has this serous bug never been noticed?

The browser 'caches' the styles when they are rendered, so even though they immediately unrender, the browser still applies them. Therefore in most scenarios, the UI renders as expected, even though the styles are no longer in the DOM.

I discovered the bug when we started using the same common component in many views. This common layout wrapper uses params so triggers the bug. We found that as we navigated between views, the styles for the component 'disintegrated'. For example, on the first navigation, the background color disappeared. On the second navigation, the padding disappeared. By the third navigation, none of the component styles were still being applied.

The navigation causes rerenders of the page section that contain the element, causing a new element to be created. It seems that each time a new element was created, the browser noticed that the CSS was no longer present in the DOM, so the styles were no longer applied. I don't know why all the styling did not disappear at once, but that is not really important.

Managing expectations:

I saw a similar bug that had a recent PR. I implemented that change but it did not fix this issue. There are numerous bugs related to the use of params, but can't find anything like this one.

I did try to trace the code to see if I could find where the logic bug is, but didn't find it. It would require a significant investment of time to reverse engineer the logic used, and I am not able to invest that right now.

My GUESS is that it is related to the logic that separates dynamic properties from static properties, but I have nothing to support that hypothesis.

It is only dumb luck that browser caching has hidden this major bug until now. There is no workaround I can find, so in our app I will remove all dynamic params as this functionality is fundamentally broken,. We can no longer rely on browser caching to hide the issue for our use cases.

Snag_50bf08f9

Snag_50bf31be

ZacharieLALOU commented 1 year ago

We noticed this after an upgrade. But we did not seem to have the issue on v10.7 We use react-jss.