-
Notifications
You must be signed in to change notification settings - Fork 47.4k
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
Ignore <noscript> content on the client and don't warn about mismatches #11423
Comments
I think that warning should be a result of the client failing to match the server side rendered content when it tries to hydrate HTML. |
Ok... I've tried removing function NoScript (props) {
const staticMarkup = ReactDOMServer.renderToStaticMarkup(props.children)
return <noscript dangerouslySetInnerHTML={{ __html: staticMarkup }} />
} return (
<span>
<NoScript>
<p>.</p>
</NoScript>
<img {...props} />
</span>
) Now I get:
So the server has encoded HTML, the client doesn't. Why would that be..? |
@gaearon Thanks for the update, and fix... I'll ignore the warning for now. Any idea when you're likely to release the next update..? |
This or next week. But I've said this a few times in the past... |
React |
@gaearon Testing now... With
However, and this maybe a separate thing, I still seem to have an issue using <span>
<noscript>
<img {...props} />
</noscript>
<img {...props} />
</span> I see this:
The HTML from the SSR (via view -> source)... <span>
<noscript>
<img src="https://d3iq5gspowosu2.cloudfront.net/dev/gifts/images/categories/483/1-300x300-beatrix-potter.jpg" class="product-image"/>
</noscript>
<img src="https://d3iq5gspowosu2.cloudfront.net/dev/gifts/images/categories/483/1-300x300-beatrix-potter.jpg" class="product-image"/>
</span> The HTML in Chrome DevTools... |
Can you please provide a reproducing project? |
@gaearon Ok... I'm a github rookie, but how is this..? https://github.com/stephen-last/react-16-noscript It's a basic app using SSR with a The only difference I can see between the server generated HTML and that shown in the DevTools, is that the |
OK, I understand why this happens now. But it’s not clear to me what’s the best fix. As a workaround you can replace this: <noscript>
<img src='https://placeimg.com/300/200/animals' width='300' height='200' />
</noscript> with this: <noscript
dangerouslySetInnerHTML={{
__html: "<img src='https://placeimg.com/300/200/animals' width='300' height='200' />"
}}
/> I verified it works and doesn’t warn. The reason you see the mismatch is because the browser is parsing the |
This seems like an earlier manifestation of this issue: #1252. Seems like in past version it was just completely broken instead of warning, but now it produces a false positive warning. |
Spoke briefly with @sebmarkbage. It's not clear how this should work. We are currently generating elements on the client with One possible solution is to treat We could implement support for setting text content to an element that can resolve to that content. Since components can return strings now. Like |
@gaearon Thanks for your time investigating this, and for the workaround suggestion. For now I'll keep a global component in my app for these tags: function NoScript (props) {
const staticMarkup = ReactDOMServer.renderToStaticMarkup(props.children)
return <noscript dangerouslySetInnerHTML={{ __html: staticMarkup }} />
} So I can use It makes sense to me to treat it as the browser does, like you suggest. |
After more discussion we settled on warning if |
@stephen-last It might be better to use |
I guess in browsers where scripts are disabled this wouldn't be parsed as text content. So it's legit to put elements in there. The issue is what happens on the client. Maybe client rendering should just ignore the content completely (and ignore hydration errors)? I don't quite fully understand the use cases where the content is used during a script enabled render. Are there such use cases? |
@sebmarkbage When I use
Using On the general I can't think of a use case for React, or any script, to use the content of |
@gaearon the |
I think we should just do this:
|
I've been tracking this issue since #1252 and #6204 so I'll chime in with our current use-case and some thoughts (long post but some background is necessary I think). We use this mainly for A/B-testing for cases where we want to determine the bucket on the client and render a component only after that. Often we still want to provide a default variant (in a noscript-tag) for people without JS, or as graceful degradation in cases where JS has crashed. Providing a noscript-fallback for conditional functionality that is determined on the client might be a bit niche but shouldn’t be that uncommon either. It could be as easy as On the server:
On the client:
TL;DR
|
About the issue at hand though, I’ve been trying to start digging into and investigating the codebase. Supressing the hydration warning does not seem that hard at a glance, but I can’t quite figure out where the best place would be to ignore the subtree of noscripts? I guess this should live in react-dom, but we would also like to make sure the reconciler doesn’t waste time on these subtrees, is there currently a valid place in the reconciler API where we could achieve this? |
Oh, and just to be clear, what I'm saying is that there is a valid usecase for using noscript content even when JS is turned on, manually simulating "noscript". We currently do this both for graceful degradation and in cases where we choose not to load the React-application for performance reasons on older devices. One should only ever have to use the content that was provided from the server in these cases though, which is why I think the proposed solution is a good one. |
A very naive way to solve this issue: // In client/ReactDOM.js
shouldSetTextContent(type: string, props: Props): boolean {
return (
type === 'textarea' ||
type === 'noscript' || // <-- This is new
typeof props.children === 'string' ||
typeof props.children === 'number' ||
(typeof props.dangerouslySetInnerHTML === 'object' &&
props.dangerouslySetInnerHTML !== null &&
typeof props.dangerouslySetInnerHTML.__html === 'string')
);
}, This solves the hydration warning, makes the reconciler ignore everything inside Not sure if there are any side effects to this, I did notice the React devtools acting a bit weird. It didn't show any content in the Not sure if anything there is indicative of something undesirable or not. I'm new to the codebase so I thought I'd mention the fix here for feedback since I might be way off, but would be happy to submit a PR for discussion if it seems feasible of course. |
hey @Ephem, are you still working on the fix? If not, then I would like to give it a go. Let me know, thanks |
Hey @muhammadInam! Since I am unsure if the direction of the fix I suggested is good I'm waiting for feedback before doing a PR, maybe @gaearon who's been active in the thread could chip in? (Only my last post is relevant in regards to a fix, rest is just background and context around how we use noscript and a bit wall-of-texty, sorry..) Basically I think my questions are:
If this is an obviously bad direction I'd be happy to let it go and let you work on it @muhammadInam, if it's not terrible at first glance I'd be happy to open a PR and continue discussions there. :) |
I tried with an
It's still coming as a string. For |
cc: @gaearon happy to try grabbing this one too if Y'all still need someone to work on it. |
Sounds good. I haven’t looked into this again yet. A proof of concept would help the conversation. |
wonderful. Putting this in my queue. ty for the quick response @gaearon |
This is most likely the wrong place to ask this question. I couldn't get on IRC or discord. I'm getting the error:
when running yarn in root. I'm running node Can anyone point me in the right direction to getting the project running on my machine? I'm on OSX. |
Yarn 0.17 sounds super old. Isn't current version 1.x something? |
I am also using the noscript tag in a project in a similar fashion as @stephen-last. I have a long page of images, most of which are lazy loaded. For the ones that are lazy loaded, there is a coresponding noscript tag containing an image tag with the target source, this is the Google recommended way to provide SEO content for lazy loaded images. |
Yes, the mere construction of the |
By adding a case to the SSR fixture I verified today that: <noscript dangerouslySetInnerHTML={{ __html: "<img src='...' /> }} /> still works in master, but that: <noscript>
<img src='...' />
</noscript> is still broken in the way described, that is, it unnecessarily downloads the image. I also verified that the solution I proposed in the comment above (adding I would still be happy to send a PR for this, including the updated fixture. I might just go ahead and do that this weekend to have a better place to discuss the proposed solution. :) |
* Ignore noscript content on the client (#11423) * Fix failing test for ignoring noscript content * Add a ServerIntegration test for noscript
Thanks @Ephem for fixing this. I think the fix makes sense but the issue itself is a bit of a mind-bender so if somebody still has problems in the next version (probably 16.4.3) please raise a new issue and reference this one. |
After update to react 16.5.0 the warning is gone and |
* Ignore noscript content on the client (facebook#11423) * Fix failing test for ignoring noscript content * Add a ServerIntegration test for noscript
React 16.0.0 with SSR & lazysizes 4.0.1.
Trying to use the "the noscript pattern" to lazy load images with lazysizes but I'm seeing this:
Image component render method:
Does React have an issue with
noscript
tags..?The text was updated successfully, but these errors were encountered: