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

Gatsby/React中Tock脚本仅页面刷新生效问题求助

解决Gatsby中Tock Reserve按钮客户端导航无效的问题

我之前也遇到过几乎一模一样的Gatsby集成Tock的问题——刷新页面按钮正常工作,但通过Gatsby的客户端路由(比如用<Link>跳转过来)就失效,核心原因是Gatsby的客户端导航不会重新执行全局脚本,Tock的初始化逻辑只在页面首次加载时运行一次,新渲染的按钮元素没被Tock识别并绑定功能。

下面是我验证有效的解决方案,分两种组件风格给你:

类组件版本(适配你现有代码)

class ReserveTock extends React.Component {
  componentDidMount() {
    this.initializeTock();
  }

  componentDidUpdate(prevProps) {
    // 如果体验ID变化,重新初始化确保按钮对应正确的资源
    if (prevProps.experienceTockId !== this.props.experienceTockId) {
      this.initializeTock();
    }
  }

  initializeTock() {
    // 避免重复加载脚本,先检查Tock是否已全局存在
    if (window.tock) {
      // 重新初始化站点,并让Tock扫描绑定页面上的按钮元素
      window.tock('init', 'websitename');
      window.tock('bindElements');
    } else {
      // 动态加载Tock脚本,加载完成后立即初始化并绑定元素
      const script = document.createElement('script');
      script.async = true;
      script.src = 'https://www.exploretock.com/tock.js';
      script.onload = () => {
        window.tock('init', 'websitename');
        window.tock('bindElements');
      };
      document.body.appendChild(script);
    }
  }

  render() {
    return (
      <a 
        className={`btn ${this.props.buttonColor} ${this.props.className}`} 
        href="https://www.exploretock.com/websitename" 
        data-tock-reserve="true" 
        data-tock-experience={this.props.experienceTockId}
      >
        Reserve
      </a>
    );
  }
}

函数组件版本(更推荐现代React写法)

import { useEffect } from 'react';

const ReserveTock = ({ buttonColor, className, experienceTockId }) => {
  useEffect(() => {
    const initTock = () => {
      if (window.tock) {
        window.tock('init', 'websitename');
        window.tock('bindElements');
      } else {
        const script = document.createElement('script');
        script.async = true;
        script.src = 'https://www.exploretock.com/tock.js';
        script.onload = () => {
          window.tock('init', 'websitename');
          window.tock('bindElements');
        };
        document.body.appendChild(script);
      }
    };

    initTock();

    // 可选:如果Tock提供销毁方法,可在这里清理(避免内存泄漏)
    return () => {
      if (window.tock) {
        // 示例:如果Tock有destroy方法,可调用 window.tock('destroy')
      }
    };
  }, [experienceTockId]); // 仅当体验ID变化时重新执行初始化

  return (
    <a 
      className={`btn ${buttonColor} ${className}`} 
      href="https://www.exploretock.com/websitename" 
      data-tock-reserve="true" 
      data-tock-experience={experienceTockId}
    >
      Reserve
    </a>
  );
};

关键修复点说明

  1. 移除render中的script标签:之前每次render都会插入新脚本,不仅冗余还可能导致冲突,改为动态按需加载脚本,确保只加载一次。
  2. 手动调用bindElements:这是解决客户端导航失效的核心——Tock默认只在脚本加载完成时扫描一次页面元素,调用这个方法会让它重新识别新渲染的按钮,绑定对应的预订功能。
  3. 生命周期/useEffect触发初始化:确保组件挂载(或props变化)时,Tock脚本已加载并完成初始化,不管是刷新页面还是客户端导航过来的场景都能生效。

另外,关于你提到的外部JS文件编译错误:第三方脚本不要放在Gatsby的src目录下(Gatsby会尝试编译它),要么用上面的动态加载方式,要么把脚本放在public目录下用绝对路径引用,但动态加载的方式更灵活可控。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 15:27:29