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

3
假设我有一个使用 React.js 构建的在线商店应用程序,我想自定义在社交媒体上分享的 URL 的外观(例如添加说明和图像),使用 HTML meta 标签。此外,我希望特定产品的路由(例如 https://www.mywebsite.com/product/<productId>)可以预览其相应的图片和说明,因此仅在 index.html 中包含 meta 标签是不可接受的。
我尝试过使用 react-helmet 和其他用于添加 meta 标签的软件包,但它们没有起作用。我猜这是因为 react-helmet 是在应用程序渲染后添加 meta 标签,而不仅仅是当 URL 在其他地方分享时。
解决这个问题的唯一方法是使用服务器端呈现,还是有办法只从前端处理?

这通常是为什么需要服务器端渲染(SSR)的原因。最基本的方法是使用ReactDOMServer。话虽如此,这也正是Next.jsGatsby等库存在的原因。 - Alexander Staroselsky
@AlexanderStaroselsky 感谢您的回复。实际上,我一直在考虑创建一个 API 端点,使用 EJS 模板呈现特定产品的适当元标记,只是想确保没有办法在没有后端的情况下处理这个问题。 - Chris Manouckson
1个回答

4

请按照以下步骤进行操作:

第一步 - 使用NPM安装以下命令

npm install react-meta-tags --save

注意:您也可以使用React Helmet(第三方库)来实现此目的。
第二步-在您的类组件中使用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,这样如果您导航到其他页面,旧的元标记将被新的替换/更新。
第三步-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提取Meta字符串
  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);

最后一个JSX布局示例是如何工作的?您需要首先加载HTML DOM,然后加载JS文件以实现React。我并不是在批评,我也有同样的想法。我只是好奇。 - BonisTech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接