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

IT技术 html reactjs react-router meta-tags react-helmet
2021-05-03 18:18:24

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

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

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

1个回答

按照下面的例子一步一步做同样的事情

步骤 1 – 使用 NPM 安装以下命令

npm install react-meta-tags --save

注意:您也可以使用React Helmet(第三方库)来实现这一点

步骤 2 – 在您的类组件中使用 MetaTag 组件

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>
      )
  }
}

注意:在标签上定义 id,因此如果您导航到其他页面,旧的元标签将被新的元标签替换/更新。

第 3 步 - ReactTitle 组件:

如果您只想在页面上添加标题,您可以使用 ReactTitle。

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>
      )
  }
}

服务器使用示例:

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);
  });
});

根据上面的代码,我们必须对服务器渲染选项执行以下操作

  1. 导入 MetaTagsServer 表单服务器
  2. 导入 MetaTagsContext 表单服务器
  3. 创建 MetaTagsServer 的新实例
  4. 将您的组件包裹在 MetaTagsContext 中并将提取方法作为props传递
  5. 使用 MetaTagsServer 实例的 renderToString 提取元字符串
  6. 将 Meta 字符串附加到您的 html 模板。

JSX 布局:

您可能还使用 React 来定义您的布局,在这种情况下,您可以使用 metaTagsInstance 中的 getTags 方法。上述服务器端示例的布局部分将如下所示。

//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);