You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React与Gatsby项目:如何按path.name重触发componentDidMount及script注入

解决Gatsby布局中根据路由重新注入TripAdvisor脚本的问题

你已经在布局组件的componentDidMount里成功实现了TripAdvisor脚本的首次注入,但因为Gatsby的布局组件通常是持久化挂载的——路由切换时不会卸载再重新挂载——所以componentDidMount只会触发一次。要实现根据path.name变化重新执行脚本注入,我们可以通过监听路由更新来触发逻辑,具体方案如下:

核心思路

  1. 把脚本注入逻辑抽成独立方法,方便复用
  2. 监听路由变化,当path.name(Gatsby中对应location.pathname)改变时,重新执行注入逻辑
  3. 每次注入前先移除旧脚本,避免页面中存在多个相同脚本导致的重复渲染或控制台错误

类组件实现方案(适配你的现有代码)

因为你当前用的是类组件,我们可以用Gatsby提供的withRouter高阶组件,把路由信息注入到组件props中,然后在componentDidUpdate里判断路由是否变化:

首先导入withRouter:

import { withRouter } from 'gatsby';

然后修改你的布局组件:

class Layout extends React.Component {
  // 抽离脚本注入逻辑,方便重复调用
  injectTripAdvisorScript = () => {
    // 先移除已存在的脚本,避免重复注入
    const existingScript = document.getElementById('tripadvisor-left-script');
    if (existingScript) {
      existingScript.remove();
    }

    const tripadvisorLeft = document.createElement("script");
    tripadvisorLeft.id = 'tripadvisor-left-script'; // 给脚本加唯一ID,方便后续定位移除
    tripadvisorLeft.src = "https://www.jscache.com/wejs?wtype=selfserveprop&uniq=789&locationId=10467767&lang=en_NZ&rating=true&nreviews=0&writereviewlink=true&popIdx=true&iswide=true&border=false&display_version=2";
    tripadvisorLeft.async = true;
    document.body.appendChild(tripadvisorLeft);
  }

  componentDidMount() {
    // 页面首次加载时执行注入
    this.injectTripAdvisorScript();
  }

  componentDidUpdate(prevProps) {
    // 对比当前路由和上一次路由,判断是否需要重新注入
    if (this.props.location.pathname !== prevProps.location.pathname) {
      this.injectTripAdvisorScript();
    }
  }

  render() {
    // 你的布局渲染逻辑
    return (
      <div className="layout-container">
        {this.props.children}
      </div>
    );
  }
}

// 用withRouter包装组件,获取路由相关props
export default withRouter(Layout);

函数组件实现方案(可选,后续重构参考)

如果之后打算把组件改成函数式写法,可以用useLocation钩子监听路由变化,配合useEffect实现:

import { useLocation } from 'gatsby';
import { useEffect } from 'react';

const Layout = ({ children }) => {
  const location = useLocation();

  useEffect(() => {
    const injectScript = () => {
      // 清理旧脚本
      const existingScript = document.getElementById('tripadvisor-left-script');
      if (existingScript) existingScript.remove();

      // 创建并注入新脚本
      const tripadvisorLeft = document.createElement("script");
      tripadvisorLeft.id = 'tripadvisor-left-script';
      tripadvisorLeft.src = "https://www.jscache.com/wejs?wtype=selfserveprop&amp;uniq=789&amp;locationId=10467767&amp;lang=en_NZ&amp;rating=true&amp;nreviews=0&amp;writereviewlink=true&amp;popIdx=true&amp;iswide=true&amp;border=false&amp;display_version=2";
      tripadvisorLeft.async = true;
      document.body.appendChild(tripadvisorLeft);
    };

    injectScript();

    // 组件卸载时清理脚本
    return () => {
      const script = document.getElementById('tripadvisor-left-script');
      if (script) script.remove();
    };
  }, [location.pathname]); // 依赖路由路径,路径变化时重新执行

  return (
    <div className="layout-container">{children}</div>
  );
};

export default Layout;

关键注意事项

  • 必须清理旧脚本:如果不先移除旧脚本,路由切换后页面会存在多个相同的TripAdvisor脚本,可能导致组件重复渲染或控制台报错
  • 路由监听的准确性:Gatsby中路由路径对应的是location.pathname,如果你的业务中需要判断更细粒度的路由参数,可以调整判断逻辑
  • 保持异步加载:脚本的async=true属性要保留,避免阻塞页面渲染

内容的提问来源于stack exchange,提问作者Darren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:37:10