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

Dynamic meta description through props

Open MiguelMachado-dev opened this issue 6 years ago • 5 comments

Is there any way that I can set a dynamic meta description thru props? I've created a component to change the Title dynamically

const HelmetCustom = ({ newtitle }) => (
  <Helmet>
    <title>Dashboard - {newtitle} </title>
    <meta name="description" content="Safe site!" />
    <meta name="keywords" content="react,helmet,dashboard" />
  </Helmet>
);

At my page file I just have to write

<HelmetCustom newtitle="Home" />

So the title can be easily passed thru props. But, how can I change the description dinamically?! I've tried using Template Strings but seems to not work

react/react-helmet version: 16.8.6/5.2.1

MiguelMachado-dev avatar Jun 05 '19 19:06 MiguelMachado-dev

Hi @mmCodingjs , I have a similar problem and I figured out that it actually does not work only if you have statically defined (without react-helmet) meta description in your index.html.

When I removed this static definitions from index.html and put general description (using react-helmet) to some of mine react components (e.g. top-level App) it started to work also for case when I "override" meta description (with react-helmet) in some child component.

As you figured out, title is working correctly also in a case when is present in index.html.

lavor avatar Aug 09 '19 08:08 lavor

Eventually found the fix here. You'll have to update it via the server if you want social cards (fb or twitter) to show the change.

See: https://github.com/facebook/create-react-app/issues/1261

TLDR; https://create-react-app.dev/docs/title-and-meta-tags#generating-dynamic-meta-tags-on-the-server https://www.kapwing.com/blog/how-to-add-dynamic-meta-tags-server-side-with-create-react-app/

There are some potential issues using ^ method if your index.html file is cached, but the way I got around that was using htmlWebpackPlugin to generate a template html file for dynamic data from the server and leave my index.html file untouched. Don't forget to sanitize your meta tags if you use the above route!

michaelolo24 avatar Sep 04 '19 20:09 michaelolo24

For my startup's Panprices client we're currently rendering on the client side. Setting a new title in a child component does trump the one set in the static HTML but my issue was that this wasn't true for meta-tags.

So for every component I'm wanting to set a custom meta description tag I'm removing the old one with the following:

componentWillMount() {
  // Remove the default static meta description in favor of react helmets dynamic one 
  if (document.querySelector("[name='description']")) {
    document.querySelector("[name='description']").remove()
  }
}

The dynamic description does gets picked up by Google who wait for the JavaScript to get rendered but for other scrapers, such as the one Facebook uses, when you post a link it would fall back to the static meta description since the scraper (at the time of writing) is less sophisticated.

t0mdicks0n avatar Sep 25 '19 08:09 t0mdicks0n

@t0mdicks0n The same behavior is achievable putting data-react-helmet="true" in each of the meta stages you are targeting to change using helmet like this:

  <meta property="og:type" content="website" data-react-helmet="true">

What happens is that react-helmet doesn't change any of the tags until either it is marked as data-react-helmet="true" (which helmet does itself) or its a title (which is one per page). What it does in response to if it doesn't find data-react-helmet="true" attribute in the tags it is supposed to change it skips the tag and creates a new one instead. I guess this should be in the read me as I also had to mess around just to know why it's happening. Also, I think the issue must be closed as I am also using react-helmet with the same pattern as @MiguelMachado-dev has created the issue for and it is working for me.

Guneetgstar avatar Sep 15 '20 15:09 Guneetgstar

Just adding what i did based on @Guneetgstar comment above to get this to work for me.

In my public/index.html <meta name="description" content="Your description." data-react-helmet="true" />

And helmet overrode with child instances (in my case i was using react-router-dom) accordingly.

prineshaz avatar Jun 01 '21 01:06 prineshaz