babel-plugin-styled-components
babel-plugin-styled-components copied to clipboard
🐞 react-responsive ssr produces collision in generated classes names
When using https://github.com/contra/react-responsive in next.js server side generated page (getServerSideProps), some components get the className wrong
this is the code (reduced for simplicity)
<MediaQuery minDeviceWidth={resolutions.MIN_LG_SIZE}>
<Row>
something here
</Row>
</MediaQuery>
<MediaQuery maxDeviceWidth={resolutions.MAX_MD_SIZE}>
<Row>
another thing here
</Row>
<Row style={{ marginBottom: '10px' }}>
yadda yadda
</Row>
</MediaQuery>
<Row>
<Col>
<ExperienceDates>
this is a styled component text
</ExperienceDates>
</Col>
</Row>
<Row style={{ marginTop: '25px' }}>
<Col sm={24}>
<Description>
another styled component, THIS HAS THE CLASS OF THE NEXT ONE, (Subtitle)
</Description>
</Col>
</Row>
<Row style={{ marginTop: '4px' }}>
<Col sm={24}>
<Subtitle>
another styled component
</Subtitle>
</Col>
</Row>
Description and Subtitle components are like this
export const Description = styled.p`
...css...
`
export const Subtitle = styled.p`
...a different css...
`
If I change the styled.p
for a styled.span
in one of them, the issue goes away.
I was a week trying to figure out what was happening, changing all sorts of configuration to no avail.
The I figured this might have something to do with <MediaQuery />
mounting/unmounting the child components and it messing around with the indices (or keys) of the internal <Row />
s or styled.p
s, so I tried reimplementing <MediaQuery />
to just being a styled component that applies display: none
with a media query (no mount/unmount), like this
export const MediaQuery = styled.div<{ minDeviceWidth?: number; maxDeviceWidth?: number }>`
@media (max-width: ${(props) => props.minDeviceWidth}px) {
display: none;
}
@media (min-width: ${(props) => props.maxDeviceWidth}px) {
display: none;
}
`
And it worked!!
The only issue is that with this implementation, all the ui (for laptop+mobile) is rendered in jsx but only is hidden with display: none
, it's a no-go for performance.