Skip to content
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

"Unable to find element with ID" when re-rendering server generated content that contains a style tag #7093

Closed
andersekdahl opened this issue Jun 21, 2016 · 27 comments
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@andersekdahl
Copy link

Do you want to request a feature or report a bug?
This is a bug.

What is the current behavior?
We server-render a page that has a style tag and the style tag is created using React.createElement. When that later gets re-rendered without a style element we see an error in the console:
capture

Note that this only happens when we server-render that page. If we turn off server rendering the error goes away. The DOM looks like this:

capture

The error also goes away if we do:

<style dangerouslySetInnerHTML={{__html: children[0]}} />

Instead of:

React.createElement(tag, props, children);

And it also goes away if we do:

React.createElement(tag, props, children[0]);

So it seems that the style element expects only one child.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/reactjs/69z2wepo/).
I haven't been able to create a small reproducable, but I hope that I've narrowed it down enough to be clear. If not then tell me and I'll try to create a reproducable again.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
15.1.0

@jimfb
Copy link
Contributor

jimfb commented Jun 21, 2016

@andersekdahl
I took a look at this one, but I wasn't able to reproduce your issue. As far as I can tell, having multiple string children for a style element appears to work fine when reviving the markup. I think we're going to need a reproducible fiddle, otherwise this isn't actionable on our end.

@jimfb jimfb added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Jun 21, 2016
@aweary
Copy link
Contributor

aweary commented Jun 21, 2016

When that later gets re-rendered without a style element

Can you clarify what you mean by this? Are you conditionally rendering the style element or something?

@andersekdahl
Copy link
Author

We render HTML that we get as a JSON structure from the server. Some of that can contain style elements (it's from a CMS and some editors gets creative). When navigating we don't reload the page, just render the new content which could be new content that doesn't include style elements.

@syranide
Copy link
Contributor

syranide commented Jun 22, 2016

Unless it has changed (since last I was involved) then <style dangerouslySetInnerHTML={{__html: children[0]}} /> is the only actually correct way. Providing a text child sometimes works (but if you have a > selector then it will be incorrectly escaped and other such issues), but I believe it will break if it ever changes value as well. So providing a text child is not actually supported.

Perhaps this is something that should be made nicer, but dangerouslySetInnerHTML is correct due to technical reasons.

@syranide
Copy link
Contributor

Simple jsfiddle to reproduce https://jsfiddle.net/muzqojcg/1/

@jimfb
Copy link
Contributor

jimfb commented Jun 22, 2016

@syranide To be clear, your fiddle is just demonstrating that the nodes a and b are broken up, when a user might expect them to be a single string? I'm not entirely clear on what your fiddle is demonstrating.

Your fiddle does not appear to trigger the invariant violation mentioned in the bug report, right? At least, I don't get an invariant on my machine. I've tested in Chrome and Firefox. We still don't have a repro of the invariant violation, right?

@syranide
Copy link
Contributor

@jimfb It was meant to showcase that it outputs the following:

<style data-reactroot="">
  <!-- react-text: 2 -->a<!-- /react-text -->
  <!-- react-text: 3 -->b<!-- /react-text -->
</style>

The comments should not be there, text is the only valid content of a style-tag, just like script-tags. You can't actually get it to throw an invariant violation due the new renderer (AFAIK), but if you resume from SSR and update the contents of the style-tag then you will get it.

Note that they are actually nodes too (if you inspect), not text content. This is wrong, to illustrate:

d = document.createElement('div');
d.innerHTML = '<style data-reactroot=""><!-- react-text: 2 -->a<!-- /react-text --><!-- react-text: 4 -->y<!-- /react-text --></style>';
d;

Outputs a style-tag with a single text child, no actual comment nodes (this is what happens when you use SSR, hence the invariant violation when trying to update it).

So, style-tags much like script-tags may only be updated with dangerouslySetInnerHTML unless we explicitly handle these tags separately. It currently renders kind of OK, but you should definitely not do it.

@andersekdahl
Copy link
Author

If dangerouslySetInnerHTML is the way to go then I'm a happy camper and the issue can be closed. Should this perhaps be added to the documentation? If you'd point me to where it should be in the docs then I can submit a PR.

@sungwoncho
Copy link

sungwoncho commented Jul 1, 2016

@andersekdahl I am getting the same error when I do server side rendering with redux-conect. But I don't have anything like React.createElement(tag, props, children); in my code.

Related issue I opened at redux-connect: makeomatic/redux-connect#36.

It only happens when one of the props updates, causing the component to be re-rendered after having been rendered on the server.

Using React 15.1.0.

Edit

After investigating, I found <style> tags on the server generated HTML. It was coming from Twitter following button widget. After removing it, I no longer get that error.

I wonder why this happens and what can be done to fix it. A solution is to render Twitter button only on the client side but that causes checksum mismatch between client and server.

@raghunandangupta1992
Copy link

I am facing same issue. I dont have any Style tag in my code, but my external CSS uses pseudo class. Therefore, :before :after are coming as DOM Nodes and invariant violation is being thrown. HOW TO SOLVE THIS ?

@calbertts
Copy link

Having a similar problem here.
I'm loading a Twitter button and it mutates the DOM throwing the error.

How can we deal with this kind of issues or third party libraries?

@mavericken
Copy link

I experienced this problem with a more simple use case:
<table><tr><td>test</td></tr></table>
When the browser loads it, the implicit tbody is added so it ends up being:
<table><tbody><tr><td>test</td></tr></tbody></table>
React freaks out because it found the TBODY tag instead of the TR tag.

It seems way too strict in my opinion. Also, I am not even sure what I am getting out of it, as I noticed that text selections are not persisting through the render, indicating to me that it is not properly reusing the elements anyways.

You can use renderToStaticMarkup to work around this issue. It is said to be less efficient, but with neither preserving text selections, I am not so sure. With renderToStaticMarkup, you will certainly have less bytes to transfer.

@alyrik
Copy link

alyrik commented Feb 12, 2017

For me this issue is caused by Facebook sharing button. I've fixed it with adding a condition to JSX to render it only on client side:

renderShare() {
    if (typeof window === 'undefined') return;
    
    return (
        /* Social buttons here */
    )
}

@AlastairTaft
Copy link

AlastairTaft commented Feb 28, 2017

I am getting this error intermittently. Often it throws the first time I load a page. When I reload the page I do not see the error again, that's not much to go on though...

UPDATE: My issue was because I was missing the <tbody /> element inside my <table /> element (same as mavericken).

@sungwoncho
Copy link

@andersekdahl I am no longer having this issue with Twitter follow button using React 15.4.1.

I also tried to reproduce it on https://github.com/sungwoncho/react-ssr-style-bug without success.

I think we can close this.

@HaraldMuehlhoffCC
Copy link

HaraldMuehlhoffCC commented Mar 12, 2017

I had this issue because I left out <tr> in the following <thead> ... took me some time to find but should be easier to find in the future.

    arbeitsbekleidung = (props) => {

        return (<div>
            <h2  {...props}>FHB Arbeitskleidung zum Sonderpreis</h2>
            <table className="table table-striped" style={{ paddingTop: "4em" }}>
                <thead>
                    <tr>
                        <th style={{ width: "40%" }}>Beschreibung</th>
                        <th>Artikelnr.</th>
                        <th>Listenpreis <GrossNetSwitcher vatRate={0.19} cookieDomain='http://*.pchfischer.com' /></th>
                        <th>Sonderpreis <GrossNetSwitcher vatRate={0.19} cookieDomain='http://*.pchfischer.com' /></th>
                    </tr>
                </thead>

PS: Today I had this issue again because I indirectly nested a div in a p (no valid html).

If I move <Img2> into the p element above I get the "Unable to find element with id ..." error.

const Img2 = (props) => <div className='text-center' style={{ paddingTop: "2em", paddingBottom: "2em" }}>
            <img alt='' src='' {...props} style={{ width: "80%" }} />
        </div>;
        
        return (
            <div>
                <p style={{ paddingTop: "2em" }}>
                    Überhaupt ist die Umsetzung von Besonderheiten, die den Seiten erst den besonderen Charme und etwas Lebendigkeit verleiten, einfach und schnell möglich:
                </p>
                <Img2 src='/images/carecom/blog/ccwebcore/oeffnungszeiten.jpg' alt="Anzeige Datum / Uhrzeit und ob aktuell geöffnet ist" />

@neomusic
Copy link

I solved my problem with style inline with
https://github.com/styled-components/styled-components

@liammclennan
Copy link

I had this problem, in my case caused by nested anchor tags, which are invalid.

Many of these problems can be solved by checking for invalid markup and fixing that.

@gethob
Copy link

gethob commented May 11, 2017

the same issue raises as I wanted to embed Facebook video in my site (localhost), but I do not know if I do it the right way in react. In my header component I put this:

componentDidMount() { (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = '//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.9&appId=1552777061651117'; fjs.parentNode.insertBefore(js, fjs); })(document, 'script', 'facebook-jssdk'); }

and the code for html of the video in one of the routes.
the video renders but when making mouseover the video I get this error:
invariant Violation: Unable to find element with ID 158
has someone may be an idea? I have never done IIFE in react..

Thank you

@chadoh
Copy link

chadoh commented Jun 4, 2017

For me, this error was caused by Cloudflare's HTML minification. Problem documentation and problem solution.

@igorescobar
Copy link

@chadoh thanks man! you saved my day!

@frozenfung
Copy link

frozenfung commented Sep 1, 2017

@chadoh 謝謝,我的網站開不起來就是因為這個原因 👍

@you3phi
Copy link

you3phi commented Oct 2, 2017

in my case , i used html p (p in p) tag nested and in webpack dev server works without error , when i build
the project and run the code in express and ssr (server side rendering) this error logged.
even though disable ssr in this component , problem not solved .
just change parent tag to <section> solved the problem.

@gaearon
Copy link
Collaborator

gaearon commented Oct 2, 2017

Whatever the cause was, this error can't possibly happen in React 16 because that code was rewritten. We also don't use comment nodes now. So I'm closing this.

If you still experience a similar error after upgrading to 16 (perhaps with a different message) please file a new issue with a reproducing example.

@gaearon gaearon closed this as completed Oct 2, 2017
@jimuyouyou
Copy link

jimuyouyou commented Nov 14, 2017

In our case(React 15.3.0), this is caused by invalid html markup, such as <a>hello</a></div></table>, which has incorrect ending as </div></table>. However, that html markup is from database, we cannot assume dba always return correct html snippet, and we have to handle this issue. Finally we decide to use https://www.npmjs.com/package/react-render-html to replace dangerouslySetInnerHTML as a work around, and it works fine.

@aradnom
Copy link

aradnom commented Feb 6, 2018

Ran into this with Optimizely rewriting a headline element on a specific page at a very bad time. Imagine you could potentially run into this with any similar services that are rewriting content on the page after load.

@u17zl
Copy link

u17zl commented Apr 21, 2020

react 15.6 with SSR, met this problem with unstructured HTML

<div>
 {isValid
  ?<div>
     {value1}
   </div>
  :{value2}
 }                 
</div>

after warping value2 with <div>:

<div>
 {isValid
  ?<div>
     {value1}
   </div>
  :<div>
    {value2}
   </div>
 }                 
</div>

Errors 🐛gone

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests