Re-rendering root node breaks dynamic styles
- Dominant language
- JavaScript
- Stars
- 7.1k
- Forks
- 386
- PR merge metrics
- No merged PRs in 30d
Description
__Expected behavior:__
The root component of a React app that is using `react-jss` for styles should be able to re-render and not break the styling of its child components.
__Describe the bug:__
This bug occurs when the root node of a React app re-renders and then later an instance of a child component unmounts when another instance of the same component mounts.
From my research, it looks like this is caused by the `indexOf` check in RuleList's [remove](https://github.com/cssinjs/jss/blob/master/packages/jss/src/RuleList.js#L117) function. The `indexOf` uses strict equality checks which fails to find a match after the re-render. The rule is no longer strictly equal due to something with how the provider works. This means that you are splicing with a -1 index, effectively removing the wrong items from the list.
```
['a', 'b', 'c'].splice(-1, 1)
// ['c']
```
This could be fixed by refactoring that line in RuleList from:
```
this.index.splice(this.index.indexOf(rule), 1)
```
to:
```
const index = this.index.findIndex(v => v.key === rule.key);
if (index > -1) {
this.index.splice(index, 1)
}
```
You could also update the provider so that it doesn't return a different object instance.
__Reproduction:__
You can see an example of this failure on this [codepen](https://codesandbox.io/s/sad-wave-7zrwwn?file=/src/app.tsx). In that example one instance of the component is unmounting while another is mounting. The cleanup function for the first instances's dynamic styles runs after the second instance has created its sheet and it removes the new sheet.
__Versions (please complete the following information):__
- jss: 10.9.2
- Browser [e.g. chrome, safari]: Chrome
- OS [e.g. Windows, macOS]: macOS
This is possibly related to https://github.com/cssinjs/jss/issues/917, though that issue has been closed.
Contributor guide
Assessment
This issue has not been assessed yet.