如何在 React.js 中添加用于共享特定 link 的元标记?

How can I add meta tags for sharing a particular link in React.js?

比如说,我有一个使用 React.js 构建的在线商店应用程序,我想自定义在社交媒体上共享的 URL 的外观(例如添加描述和图像)使用HTML 元标记。此外,我希望特定产品的路线(例如https://www.mywebsite.com/product/<productId>)可以预览适当的图片和描述,因此仅在元标记中包含元标记是不可接受的index.html.

我曾尝试使用 react-helmet 和其他用于添加元标记的软件包,但它们没有帮助。我想,这是因为 react-helmet 在应用呈现后添加了元标记,而不仅仅是在 URL 在某处共享时。

这个问题的唯一解决方案是使用服务器端渲染,还是有办法只从前端处理它?

Follow the below example step by step to do the same

Step 1 – Install below command Using NPM

npm install react-meta-tags --save

Note: You can also achieve this using React Helmet (a third party library)

Step 2 – Use MetaTag Component in your class Component

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

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

Note: Define id on tags so if you navigate to other page, older meta tags will be replaced/update by new ones.

Step 3 - ReactTitle Component:

If you just want to add title on a page you can use ReactTitle instead.

import React from 'react';
import {ReactTitle} from 'react-meta-tags';

class Component2 extends React.Component {
  render() {
    return (
        <div className="wrapper">
          <ReactTitle title="Your Page 2"/>
          <div className="content"> Your Page 2 Content </div>
        </div>
      )
  }
}

The Server Usage Example:

import MetaTagsServer from 'react-meta-tags/server';
import {MetaTagsContext} from 'react-meta-tags';

/* Import other required modules */
/*  some serve specific code */

app.use((req, res) => {
  //make sure you get a new metatags instance for each request
  const metaTagsInstance = MetaTagsServer();

  //react router match
  match({
    routes, location: req.url
  }, (error, redirectLocation, renderProps) => {
    let reactString;

    try{
      reactString = ReactDomServer.renderToString(
      <Provider store={store}> 
      {/*** If you are using redux ***/}
      {/* You have to pass extract method through MetaTagsContext so it can catch meta tags */}

        <MetaTagsContext extract = {metaTagsInstance.extract}>
          <RouterContext {...renderProps}/>
        </MetaTagsContext>
      </Provider>
      );
    }
    catch(e){
      res.status(500).send(e.stack);
      return;
    }

    //get all title and metatags as string
    const meta = metaTagsInstance.renderToString();

    //append metatag string to your layout
    const htmlStr = (`
      <!doctype html>
      <html lang="en-us">
        <head>
          <meta charSet="utf-8"/>
          ${meta}
        </head>
        <body>
          <div id="content">
            ${reactString}
          </div>
        </body>
      </html>  
    `);

    res.status(200).send(layout);
  });
});

As per the above code we have to do following for server rendering options

  1. Import MetaTagsServer form server
  2. Import MetaTagsContext form server
  3. Create a new instance of MetaTagsServer
  4. Wrap your component inside MetaTagsContext and pass extract method as props
  5. Extract Meta string using renderToString of MetaTagsServer instance
  6. Append Meta string to your html template.

JSX Layout:

You might also be using React to define your layout, in which case you can use getTags method from metaTagsInstance. The layout part of above server side example will look like this.

//get all title and metatags as React elements
const metaTags = metaTagsInstance.getTags();

//append metatag string to your layout
const layout = (
  <html lang="en-us">
    <head>
      <meta charSet="utf-8"/>
      {metaTags}
    </head>
    <body>
      <div id="app" dangerouslySetInnerHTML={{__html: reactString}} />
    </body>
  </html>  
);

const htmlStr = ReactDomServer.renderToString(layout);

res.status(200).send(htmlStr);