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

Title component doesn't override default <title> tag provided via HTML template #83

Open
rdsedmundo opened this issue Apr 22, 2019 · 10 comments

Comments

@rdsedmundo
Copy link
Contributor

rdsedmundo commented Apr 22, 2019

I'm using client-side rendering and react-head is not able to replace a default tag that I provided on my HTML template. It only adds a new <title> tag at the end of the head, and due to the browser behavior, only the first one is actually used. react-helmet as a reference supported this fine.

template.html

<html>
  <head>
    <title>Test</title>
  </head>
  <body>
     <div id="react-mount"></div>
  </body>
</html>

index.js

import React from 'react';
import ReactDOM from 'react-dom';

import { Title, HeadProvider } from 'react-head';

ReactDOM.render(
  <div>
    <HeadProvider>
      <Title>Test2</Title>
    </HeadProvider>
  </div>
  document.getElementById('react-mount'),
)

The expected behavior for me is that Test2 is going to replace and be the title of the page, but what happens is that Test remains as the title, as its tag is positioned first.

@rdsedmundo
Copy link
Contributor Author

Nevermind, I realized what is going on in fact. The nesting is working. The problem is that, if I provide a default tag on my HTML template, react-head won't override it and it always stays on the top and "won the battle" compared to the tag that react-head inserts.

I'll change the title and description appropriately.

@rdsedmundo rdsedmundo changed the title Nested Title tags are not working Title component doesn't override default <title> tag provided via HTML template Apr 22, 2019
@tizmagik
Copy link
Owner

I guess what is the desired behavior here? I'm not sure react-head should mess with existing markup on the page. Curious what your use case is for the title to be part of the template vs having react-head completely manage it?

@rdsedmundo
Copy link
Contributor Author

It's simply because this one can act as a default one and if I share the webpage on Slack, for example. If I do that and have the <title> tag on the HTML I can see the title being picked up. Relying only on react-head Slack won't get anything, as JS won't execute. And by the way, we don't have strong SEO requirements that would justify adding server-side rendering, the use case is really just this quick link sharing on a platform here and there.

@tizmagik
Copy link
Owner

Yes, makes total sense to have a fallback as part of the template @rdsedmundo 👍

However, I'm not sure react-head should manage that. Conceptually my mental model is when you import { Title } from 'react-head' then you're telling react-head to manage that Title tag -- I'm not sure it makes sense for react-head to manage all title tags.

To solve your use case though I guess it would be relatively easy to add a small snippet to remove the title tag that the template adds and then the rest would be left up to react-head:

<head>
  <title id="template-title">Template Title</title>
</head>

<script>
const templateTitle = document.getElementById("template-title");
if (templateTitle) templateTitle.parentNode.removeChild(templateTitle);
</script>

@TrejoCode
Copy link

Yes, makes total sense to have a fallback as part of the template @rdsedmundo 👍

However, I'm not sure react-head should manage that. Conceptually my mental model is when you import { Title } from 'react-head' then you're telling react-head to manage that Title tag -- I'm not sure it makes sense for react-head to manage all title tags.

To solve your use case though I guess it would be relatively easy to add a small snippet to remove the title tag that the template adds and then the rest would be left up to react-head:

<head>
  <title id="template-title">Template Title</title>
</head>

<script>
const templateTitle = document.getElementById("template-title");
if (templateTitle) templateTitle.parentNode.removeChild(templateTitle);
</script>

Thank you, I stopped using react-head precisely for not having this feature, it is very, the proposed solution is simply horrible, nothing clean.
I hope in some future it will be corrected and I can return to this compenente.

  • Thank you anyway.

@tizmagik
Copy link
Owner

tizmagik commented Oct 6, 2019

I’m curious how others feel about this. If there’s enough interest in having react-head clobber existing tags on the page that it otherwise does not manage, we can look into adding support.

@JoshuaToenyes
Copy link

JoshuaToenyes commented Oct 6, 2019

Personally, my mental model says that existing tags should not be modified by react-head. The real solution here is SSR.

Although the title tag might seem special in this case, how would react-head handle other singleton type tags (i.e. <meta name="viewport" ...>). Would it clobber those too?

I image troubleshooting unexpectedly changing tag values to be more difficult than seeing duplicate tags and realizing one is being injected by react-head, and the other hardcoded in the template.

Also, expecting react-head to clobber the other title tags could lead to problems if you are using SSR. Suppose you had a hard-coded title tag in your template (or interpolated through some other means), then inject another title tag via react-head. The resulting HTML will have two title tags (bad for a number of reasons). However, inspecting the page after JS has executed and react-head has removed the original title tag will make it appear as though there's no problem.

@TrejoCode
Copy link

Personally, my mental model says that existing tags should not be modified by react-head. The real solution here is SSR.

Although the title tag might seem special in this case, how would react-head handle other singleton type tags (i.e. <meta name="viewport" ...>). Would it clobber those too?

I image troubleshooting unexpectedly changing tag values to be more difficult than seeing duplicate tags and realizing one is being injected by react-head, and the other hardcoded in the template.

Also, expecting react-head to clobber the other title tags could lead to problems if you are using SSR. Suppose you had a hard-coded title tag in your template (or interpolated through some other means), then inject another title tag via react-head. The resulting HTML will have two title tags (bad for a number of reasons). However, inspecting the page after JS has executed and react-head has removed the original title tag will make it appear as though there's no problem.

It is correct thought in SSR.
My approach is for the CSR.

@tizmagik
Copy link
Owner

If anyone's interested in working on this, I think a PR to show how this might work would be helpful. Ideally there should be a way to opt-in (or opt-out) of clobbering.

@tizmagik
Copy link
Owner

Wrote up a quick RFC: #97

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants