-
Notifications
You must be signed in to change notification settings - Fork 237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No "working" styled-components example #167
Comments
Until the root-cause of this is hopefully resolved with react 18.3 you can try out remix-island or a similar approach to hydrate only parts of the document. It works reliably on my end with styled-components (can't stream them though) |
Unrelated to this issue, but might still be interesting. I’ve recently created a CSS-in-JS library that builds CSS like Tailwind, and doesn’t require a Babel/esbuild plugin. Specifically for having no issues with Remix. Read more here: https://github.com/roj1512/classno |
Both the remix and the react team are aware of this issue. React is actively working towards a solution as this is affecting any solution that hydrates react into the complete On my end, https://github.com/kiliman/remix-hydration-fix and https://github.com/Xiphe/remix-island present good enough workarounds until the problem will eventually be fixed at it's root cause. You can also try to downgrade react to v17. |
Thanks for raising this issue! I've just merged a PR that updates our Styled Components example to address the issues mentioned here. If you're still experiencing issues, let us know, or even help us improve the example if there's something we missed. |
Hi @markdalgleish thanks for taking the time to update the example on this! Indeed, the change you added to the example should make it so styled components itself don't cause hydration issues. The problem is that when anything else produces a hydration error, react will wipe away the To me that's not a state in which I would ship an app to production. I understand that there's little to nothing we can do about this from within remix itself (Other then maybe officially supporting rendering into a smaller part of the page) and the update you did on the example is certainly helpful. Still I wouldn't consider this issue fixed. |
Hey ya'll! Is there any thought on getting an example together with Vite + Styled Components since this seems to be the direction Remix is going? |
Would love to know that as well - just starting to explore Remix + Vite, and |
@seanmcquaid @mryechkin hey guys, have you managed to successfully integrate |
I did using
// app/root.tsx
export const Head = createHead(() => {
return (
<>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</>
)
})
export default function App() {
// this will be rendered inside a node
return (
<ThemeProvider>
<Outlet />
</ThemeProvider>
)
}
// app/entry.server.tsx
import { PassThrough } from 'node:stream'
import {
createReadableStreamFromReadable,
type EntryContext,
} from '@remix-run/node'
import { RemixServer } from '@remix-run/react'
import { isbot } from 'isbot'
import { renderToPipeableStream } from 'react-dom/server'
import { renderHeadToString } from 'remix-island'
import { ServerStyleSheet } from 'styled-components'
import { Head } from './root'
const ABORT_DELAY = 5_000
export function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
) {
const styleSheet = new ServerStyleSheet()
return new Promise((resolve, reject) => {
let shellRendered = false
const { pipe, abort } = renderToPipeableStream(
styleSheet.collectStyles(
<RemixServer
context={remixContext}
url={request.url}
abortDelay={ABORT_DELAY}
/>,
),
{
onShellReady() {
shellRendered = true
responseHeaders.set('Content-Type', 'text/html')
const head = renderHeadToString({
request,
remixContext,
Head,
})
const body = injectStyles(head, styleSheet, pipe)
const stream = createReadableStreamFromReadable(body)
resolve(
new Response(stream, {
status: responseStatusCode,
headers: responseHeaders,
}),
)
},
onShellError(err: unknown) {
reject(err)
},
onError(err: unknown) {
if (shellRendered) {
console.error(err)
}
},
},
)
setTimeout(abort, ABORT_DELAY)
})
}
function injectStyles(
head: string,
styleSheet: ServerStyleSheet,
pipe: <Writable extends NodeJS.WritableStream>(
destination: Writable,
) => Writable,
) {
const body = new PassThrough()
body.write(
`<!DOCTYPE html><html><head>${head} ${styleSheet.getStyleTags()}</head><body><div id="root">`,
)
pipe(body)
body.write('</div></body></html>')
return body
}
import { RemixBrowser } from '@remix-run/react'
import { StrictMode, startTransition } from 'react'
import { hydrateRoot } from 'react-dom/client'
startTransition(() => {
hydrateRoot(
document.getElementById('root')!,
<StrictMode>
<RemixBrowser />
</StrictMode>,
)
}) |
I know @Xiphe had already recommended the |
Awesome! Thanks for sharing @prxg22 |
You rock @prxg22 🪨 ! Thank you so much for sharing ❤️ |
Still having hydration issues though, seems like its' related with an external library i am using because everything seems to work fine, anyone having any ideas? |
can you share the current code of your root.tsx & entry.server.tsx ? i also had some issues first and than could resolve it by adapting the |
@wetteyve
and this is my entry.server.tsx file:
As u can see i am also working with i18n, apollo and a custom provider |
@AronH99 Ok these files look good from my point of view. I have also wrapped my remixApp in additional providers and added a script tag, everything works without hydration errors. I'm sorry I can't help you any further. When looking for hydration errors, it sometimes helps me to look at the HTML diffs as described here: https://www.jacobparis.com/content/remix-hydration-errors#-tip-diff-the-html-to-find-the-exact-cause |
@wetteyve thanks for the tip, it's most likely because of the external import of a component library but can't seem to solve it, i will look a little more though |
This solution worked for me: styled-components/styled-components#4275 |
Still getting the issue @prxg22
|
I was able to solve it, take a look at my comment here: #375 (comment) |
What version of Remix are you using?
1.12.0
Are all your remix dependencies & dev-dependencies using the same version?
Steps to Reproduce
official styled-components example
Expected Behavior
That it will render both on first load as well as consecutive loads without err.
Actual Behavior
Exhibits the hydration issues mentioned here.
However, in our experience, the styles match fine on FIRST load. Only on page refresh do them become broken. Even with JS disabled this issue persists, which leads me to believe the issue is strictly an SSR one for the moment.
It does not appear that it will work with any SSR without the aid of babel-plugin-styled-components which itself is not supported in Remix since it doesn't seem we have access to plugins or modifying esbuild config.
As a comparison, Next.js allows you to control webpack option values from a configuration file (next.config.js) so they can implement the needed plugins. A member of the development team says in a PR comment that this is because exposing the configuration values would lock in the compiler's choices and also risk breaking the application.
This limitation seems to be leading some remix users to implement workarounds using a custom module to override esbuild.
Then there are a number of other mentions out there of similar issues that link around and I'm not even quite sure if its relates to the same hydration issue or not, but certainly sounds like it would affect the existing example.
There are even posts about how to do this with NextJS that say there are no issues.... but that seems odd when the example doesnt seem to need
babel-plugin-styled-components
.@kentcdodds mentions a possible fix here using patch-package, however then @jmurzy mentions that the needed code is stripped out, rendering that possible fix incomplete.
For added injury, we also need to get Material-UI v4 working, which seems to have exactly the same issue. First load, all the style names match up, on reload, none match. This is also with JS disabled, so it appears again to be an SSR only issue.
Conclusion
None of the methods above seem to work for us, and we're currently not clear if its because we use pnpm or that it's a monorepo, or that we also implement our own custom react ui lib that also uses
babel-plugin-styled-components
but in any case, none seem to work.We're VERY much wanting to migrate all our sites to Remix but need to slowly migrate away from styled-components, and not cold-turkey cut it off. So we need a migration path for styled-components with Remix.
The text was updated successfully, but these errors were encountered: