react-head icon indicating copy to clipboard operation
react-head copied to clipboard

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

Open rdsedmundo opened this issue 5 years ago • 10 comments

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 avatar Apr 22 '19 18:04 rdsedmundo

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 avatar Apr 22 '19 18:04 rdsedmundo

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?

tizmagik avatar Apr 23 '19 02:04 tizmagik

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.

rdsedmundo avatar Apr 23 '19 10:04 rdsedmundo

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>

tizmagik avatar Apr 24 '19 16:04 tizmagik

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.

TrejoCode avatar Oct 06 '19 00:10 TrejoCode

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.

tizmagik avatar Oct 06 '19 16:10 tizmagik

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.

JoshuaToenyes avatar Oct 06 '19 23:10 JoshuaToenyes

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.

TrejoCode avatar Oct 07 '19 13:10 TrejoCode

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 avatar Oct 11 '19 19:10 tizmagik

Wrote up a quick RFC: https://github.com/tizmagik/react-head/issues/97

tizmagik avatar Oct 14 '19 16:10 tizmagik