facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
228.05k stars 46.54k forks source link

Bug: SSR: "Text content did not match" for inline CSS in style element #26946

Closed EmielM closed 1 month ago

EmielM commented 1 year ago

When using Server Side Rendering for the complete document (as suggested in the docs), and having inline css that contains quotes (", ') in a style element:

function App() {
  return <html>
    <head>
      <style>body { font-family: "Comic Sans"; }</style>
    </head>
  </html>;
}

The quotes are encoded by react-dom/server as &quot;, and client-side hydration chokes:

Warning: Text content did not match. Server: "body { font-family: &quot;Comic Sans&quot;; }" Client: "body { font-family: "Comic Sans"; }"
    at style
    at head
    at html
    at App2
printWarning @ bundle.js:2426

React version: 18.2.0 Reproducing case: https://github.com/EmielM/react-ssr-reconcile-repro

For completeness, the verbatim HTML output from the server:

<!DOCTYPE html><html><head><style>body { font-family: &quot;Comic Sans&quot;; }</style></head><body>Body!</body></html><script src="/bundle.js" async=""></script>
Shurtu-gal commented 1 year ago

@EmielM Remove the quotes. They are unnecessary

createElement('style', {}, 'body { font-family: Comic Sans; }')

EmielM commented 1 year ago

@Shurtu-gal this is a synthetic/simplified example, there are cases when you really need a quote in your css, eg for content: '"', or selectors such as a[href="https://…"]. In any case, react-dom should handle this correctly.

YantD729 commented 1 year ago

I think it is a problem on hydration on CSR. Although this is my first issue, I would like to have a try. Do you mind to assign it to me? Thank you :3 I will update immediately once I feel not okay to solve it.

EmielM commented 1 year ago

@YantD729 We're still having this, would you mind :)?

kotarella1110 commented 10 months ago

I have encountered this issue as well. While it's a somewhat hacky solution, you can bypass the encoding of quotes and eliminate hydration errors by using dangerouslySetInnerHTML to create a style element.

function App() {
  return <html>
    <head>
      <style dangerouslySetInnerHTML={{ __html: "body { font-family: "Comic Sans"; }" }}></style>
    </head>
  </html>;
}

HTML output:

<!DOCTYPE html><html><head><style>body { font-family: "Comic Sans"; }</style></head><body>Body!</body></html><script src="/bundle.js" async=""></script>
jereaa commented 7 months ago

I'm having the same issue when rendering with renderToPipeableStream. As for my example, you just need to refer to React's new documentation for the <style> tag under react/dom.

image

Same thing happens with inline scripts and characters like & that get encoded.

github-actions[bot] commented 4 months ago

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

jereaa commented 4 months ago

Still an issue

github-actions[bot] commented 1 month ago

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

github-actions[bot] commented 1 month ago

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!