react: "Unable to find element with ID" when re-rendering server generated content that contains a style tag
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:
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:
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
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 24
- Comments: 27 (6 by maintainers)
For me, this error was caused by Cloudflare’s HTML minification. Problem documentation and problem solution.
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?
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.
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.
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.
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.