-
Notifications
You must be signed in to change notification settings - Fork 47.1k
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
noscript contents cause invariant violation #1252
Comments
Now that we have
where |
We should just make noscript do this automatically, sort of like our existing wrappers for input, select, and textarea. Want to take a crack at it? |
Sure. I'll try to get a PR in soon. |
I'd love it if somebody could revisit this issue - it's a real pain to have to use the workaround |
Related #1905 ... should we even set the content of PS. I feel like there's something dirty about |
Yeah, I think I suggested ignoring As for rendering to a string, it may be dirty but, in my opinion, it's the acceptable kind of dirtiness since it protects the user from the inherent complexity of dealing with a wonky browser bug. I guess you could argue that |
@matthewwithanm Oh right, yeah, reusing client-side would require a special flag internally which would use server-rendering rules when constructing the initial markup. |
For future searchers, here is this workaround wrapped up into a component. In this case set up as an ES6 CommonJS module that relies on the constant const React = require('react/addons');
module.exports = React.createClass({
displayName: 'NoScript',
mixins: [React.PureRenderMixin],
render() {
if (process.browser)
return <noscript/>;
else
return <noscript dangerouslySetInnerHTML={
{__html: React.renderToStaticMarkup(this.props.children)}
}/>;
}
}); |
I'd like to use this workaround, but it seems to be deprecated: Warning: React.renderToStaticMarkup is deprecated. Please use ReactDOMServer.renderToStaticMarkup from require('react-dom/server') instead. I'm guessing that |
@Jpunt me too. Being able to convert a React component to static markup on the client came in handy sometimes. |
@jimfb you da MAN. Thanks, that's very helpful! |
@Jpunt @jimfb ( /cc @benkeen ) Maybe there are uses for rendering static markup on the client but If react is running then the var React = require('react');
var is = {
browser: require('lib/is/browser')
};
var ReactDOM;
if ( ! is.browser()) {
ReactDOM = require('react-dom/server')
}
var NoScript = React.createClass({
mixins: [ React.PureRenderMixin ],
render: function () {
if (is.browser()) {
return <noscript/>;
}
else { // on server
return <noscript dangerouslySetInnerHTML={
{ __html: ReactDOM.renderToStaticMarkup(this.props.children) }
} />;
}
}
});
module.exports = NoScript; You'll want to alias the react server code to resolve to empty module since it's unlikely you're bundler will figure it out on it's own; not with out some other rules in place anyway. If you use webpack add the following to your configuration: resolve: {
alias: {
"react-dom/server": "empty-module"
}
}, And make sure you have |
@srcspider: Could you explain why you choose to render an empty noscript on the client instead of the same noscript with dangerouslySetInnerHTML? When I try to do this I get a server-side rendering mismatch
which totally makes sense. Rendering the static HTML in all cases works for me, and should be fine performance-wise with the pure-render decorator. |
I think this issue should be highlighted somewhere on the documentation. The following seems to work well for me both on client and server (thanks to people above):
import React from 'react';
import ReactDOM from 'react-dom/server';
export default function Noscript(props) {
// https://github.com/facebook/react/issues/1252
const staticMarkup = ReactDOM.renderToStaticMarkup(
props.children
);
return <noscript dangerouslySetInnerHTML={{ __html: staticMarkup }} />;
} Usage: import Noscript from './Noscript.js'; <Noscript>
<div className="noJavascript">
<div>
<p>
Your browser has disabled Javascript. Please note this website requires Javsacript to function correctly.
</p>
</div>
</div>
</Noscript> |
@BabakMN This is a good first-order approximation (and I use it), but it has the severe limitation that you cannot nest |
I believe React 16 doesn’t crash on this anymore, even though it produces a false positive warning. |
When using server rendering, putting an
<img>
in a<noscript>
seems to invariably cause an invariant violation (it can't find the image).I believe this is because, to the JS enabled browser, the noscript content looks like CDATA.
This can be worked around by using
dangerouslySetInnerHTML
to actually set the contents to an HTML string, however, you can't nest components with this approach.The text was updated successfully, but these errors were encountered: