Reactjs, change the favicon in componentDidMount

Viewed 2787

I want to change the favicon of the Reacjs application according to some properties. I already have saved the icons in public folder but cannot find a way to give the path as href to a newly created element.

  componentDidMount() {
    const { project } = this.props.rootStore!;
    let link = document.createElement('link');
    const oldLink = document.getElementById('favicon');
    link.id = 'favicon';
    link.rel = 'shortcut icon';
    link.href = // here I tried the following string literals
    if (oldLink) {
      document.head.removeChild(oldLink);
    }
    document.head.appendChild(link);
  }

link.href='%PUBLIC_URL%/assets/images/' + project.id + '/favicon.ico';
// TypeError: Cannot read property 'id' of undefined

link.href = `%PUBLIC_URL%/assets/images/${project.id}/favicon.ico`;
// TypeError: Cannot read property 'id' of undefined

link.href = '%PUBLIC_URL%/assets/images/${project.id}/favicon.ico';
// GET http://localhost:3000/demo/category/showroom/%PUBLIC_URL%/assets/images/$%7Bproject.id%7D/favicon.ico 400 (Bad Request)

Now my question can be first: what is the best way to change the favicon in Reacjs (I searched a lot but did not find any answer). second: how should I define the href.

3 Answers

There is no best way to do this. React offers no functionality to deal with existing DOM elements outside the application. This should be done in React as it would be done in vanilla JavaScript:

let link = document.querySelector('link[rel="shortcut icon"]') ||
  document.querySelector('link[rel="icon"]');

if (!link) {
    link = document.createElement('link');
    link.id = 'favicon';
    link.rel = 'shortcut icon';
    document.head.appendChild(link);
}

link.href = `/assets/images/${id}/favicon.ico`;

href should preferably contain absolute path or URL to provide correct icon location regardless of base URL.

One React-y way to do this is using react-helmet

With that library you can change the elements inside the <head>

Eg.

import Helmet from 'react-helmet'

...

<Helmet>
  <title>ABC</title>
  <meta name="ABC" content: "ABC" />
  <link rel="icon" type="image/png" href="favicon.ico" sizes="16x16" />
</Helmet>

npm install react-meta-tags --save

https://github.com/s-yadav/react-meta-tags

Very happy with this in my projects. Helmet is another option.

import React from 'react';
import MetaTags from 'react-meta-tags';

class Component1 extends React.Component {
  render() {
    return (
        <div className="wrapper">
          <MetaTags>
            <title>Page 1</title>
            <meta name="description" content="Some description." />
            <meta property="og:title" content="MyApp" />
            <meta property="og:image" content="path/to/image.jpg" />
          </MetaTags>
          <div className="content"> Some Content </div>
        </div>
      )
  }
}
Related