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

Next.js项目嵌入Clutch.co Widget遇渲染及Hydration失败问题求助

解决Next.js中嵌入Clutch.co Widget的渲染及Hydration失败问题

先明确你两个方案的核心问题:

  1. 方案一问题:

    • 脚本未加载完成就渲染容器,Clutch初始化逻辑找不到目标元素
    • 直接在useEffect中设置setShowWidget(true),导致服务端与客户端渲染内容不匹配,触发Hydration失败
    • 清理函数直接执行removeChild可能触发DOM操作错误
  2. 方案二问题:

    • ClutchWidget组件没有return JSX元素,根本不会渲染任何内容

正确实现步骤

1. 编写客户端专属组件(避免SSR/SSG冲突)

创建带"use client"的组件,确保脚本加载完成后再渲染容器并触发初始化:

"use client";

import { useEffect, useState } from "react";

export default function ClutchWidget() {
  const [isScriptLoaded, setIsScriptLoaded] = useState(false);

  useEffect(() => {
    // 检查脚本是否已存在,避免重复注入
    const existingScript = document.querySelector('script[src="https://widget.clutch.co/static/js/widget.js"]');
    if (existingScript) {
      setIsScriptLoaded(true);
      window.clutchWidget?.init();
      return;
    }

    const script = document.createElement("script");
    script.src = "https://widget.clutch.co/static/js/widget.js";
    script.async = true;

    // 脚本加载完成后再渲染容器并初始化
    script.onload = () => {
      setIsScriptLoaded(true);
      window.clutchWidget?.init();
    };

    script.onerror = () => {
      console.error("Clutch Widget 脚本加载失败");
    };

    document.body.appendChild(script);

    // 安全清理脚本
    return () => {
      if (script.parentNode) script.parentNode.removeChild(script);
      delete window.clutchWidget;
    };
  }, []);

  // 仅在脚本加载完成后渲染容器,避免Hydration不匹配
  return isScriptLoaded ? (
    <div
      className="clutch-widget"
      data-url="https://widget.clutch.co"
      data-widget-type="3"
      data-height="320"
      data-nofollow="true"
      data-expandifr="true"
      data-scale="100"
      data-reviews="2220706,2123032,2113547"
      data-clutchcompany-id="2108125"
    />
  ) : null;
}

2. 在页面中正常引入组件

Page.js保持原有逻辑即可:

import ClutchWidget from "./components/Testimonials/ClutchWidget";

export default function Home() {
  return (
    <div>
      <ClutchWidget />
    </div>
  );
}

关键优化说明

  • 避免重复加载:先检查DOM中是否已有目标脚本,防止多次注入
  • 脚本加载后再渲染:确保Clutch初始化时能找到目标容器,同时避免服务端与客户端渲染内容不匹配(服务端返回null,客户端仅在脚本就绪后渲染)
  • 手动触发初始化:处理脚本从缓存加载、容器后渲染的边界情况
  • 安全清理:避免直接移除不存在的DOM元素导致报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:05:00