styled-components: SSR: class order is not persisted

SSR + styled-components:

const A = styled.div`
  position: relative;
`
const B = styled(A)`
  position: absolute;
`

It happens that element B has position: relative (the order of generated classes is wrong) from time to time. It only happens when using SSR and not on all elements… pretty weird… Has anyone exprerienced the same isssue? I can create proper issue using the bug template if necessary.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 24
  • Comments: 27 (3 by maintainers)

Most upvoted comments

@tbekaert That’s a very astute observation. I made this comment back then and I believe that could be what’s happening here. Since the PR in question doesn’t actually fix anything we can probably just revert it. Have you by any chance tried that and built a preview version?

I still think we have to further test and think whether it holds true though, since SSR results may be very much out of order, if preregistration fails.

I believe I simply never quite got to testing this before this was already pushed out.

Since no one here seems to have a reproduction (@antoinerousseau A production site with just a link is not a reproduction, it’s just showing me that either you or we made a mistake) that’d probably be able to confirm that this is the issue.

@Filipeue So this is where it gets interesting, I do believe that #3233 could be causing some issues. But I’m assuming that people here have correct setups. If your setup is broken then that’d obviously entirely unrelated. And given that you see issues regardless of version ranges that’s likely here.

Since this happens in a lot of our issues it’s almost impossible to see which issues are relevant or not. So please refrain from comments just because you’re desperate for a fix. They don’t move this along 😅

@marhalpert your issue is also unrelated. You’re writing about the combinator selector there and not about SSR ordering.

So tl;dr: @tbekaert @antoinerousseau You seem to have solid cases that can reproduce the bug. Would it help if I provided a pre-release with this PR reverted? I’d also love to know more about your SSR setup to make sure that it’s not causing the issue through other means 🙌

Even downgrading to 5.2.0 did not help for me Anyone has minimal codepen setup for styled-components SSR?

@Filipeue well that’s good but it’s still an ugly hack for an issue that should not exist. 🤷

@kitten We have been wrestling with what sounds like this exact same issue.

TL;DR Downgrading to SC v5.2.0 fixes it for us.

This makes little sense, if your change logs are accurate though, since 5.2.1 looks like only 3 small unrelated commits if we are reading this right?

We have reproduced the issue in a demo, BUT its super odd and requires the use of an external lib that has a peer dependency on SC. Since our lib is private, I can’t really provide that, but happy to talk thru it if this example is at all helpful.

Repo Steps:

  1. yarn build && serve
  2. Browse to Home page (index.js)
  3. Click the link named “link”. This should link you to Page 2.
  4. When you get here… notice the background of the text “Page 2” will be RED
  5. Hard refresh the page and watch the text background change to Green.

ezgif-6-f15841c15fc8

EXPECTED: The background of the text should be GREEN regardless if navigated to OR hard refreshing.

ACTUAL: The background of the text is RED. until hard refeshing

The only code of note in this base gatsby install repo is…

/gatsby-ssr.js Notice here we only simply only importing from our external lib (with peer dep on SC) and not even using it. Also, using setPostBodyComponents to inject meaningless div. Removing EITHER of these will fix the issue.

import { consoleKlickSignature } from '@klickmarketing/react-components'

const React = require('react')

export const onRenderBody = ({
  setBodyAttributes,
  setPostBodyComponents,
  setHeadComponents,
}) => {
  setPostBodyComponents([<div>hello</div>])
}

/P.js (Custom Paragraph Component)

import styled from 'styled-components'

const P = styled.p`
  background: red;
`

export { P }

/index.js (HOME PAGE)

import React from "react"
import styled from 'styled-components'
import { P } from '../components/P'
import { Link } from "gatsby"

const IndexPage = () => (
  <div>
  <Link to="/page-2">link</Link>
  <OtherP>Page 1</OtherP>
</div>
)

const OtherP = styled(P)`
  background: green;
`

export default IndexPage

/page-2.js (PAGE 2)

import React from "react"
import styled from 'styled-components'
import { P } from '../components/P'

const SecondPage = () => (
  <div>
  <StyledP>Page 2</StyledP>
</div>
)

const StyledP = styled(P)`
  background: green;
`

export default SecondPage

Sigh… back to this same issue again. This time its even WITH styled-components v5.2.3 babel-plugin-styled-components@1.10.5

However, styled-components@5.2.3 uses babel-plugin-styled-components@1.12.0 internally. We tried using a resolution to drop it to match 1.10.5 but then we would get errors.

image

FIXED We managed to find a fix to our issue. It appears this issue has already been identified in another issue on babel-plugin-styled-components.

for anyone still dealing with the issue, my findings are that class order is not always persisted and you should not rely on it being persisted till the issue is resolved instead you can safely override style like this:

const A = styled.div`
  color: black;
`
const B = styled(A)`
  && {
    color: red;
  }
`
const C = styled(B)`
  &&& {
    color: green;
  }
`

this way A will be black, B red and C green