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

将YouGlish API代码转为React应用:点击按钮无响应问题排查

解决React中YouGlish Widget无法加载的问题

你的代码存在几个核心问题,导致点击按钮后无法正常渲染视频界面,以下是针对性的修复方案:

问题分析

  1. 组件渲染逻辑错误:直接调用YouglishWidget()函数不会将返回的DOM元素插入React的渲染树,React要求组件通过条件渲染方式加载。
  2. 脚本重复加载:每次点击按钮都会插入新的widget.js脚本,引发重复初始化冲突。
  3. 回调函数作用域问题:onYouglishAPIReady未绑定到全局,YouGlish脚本加载后无法触发;onCaptionConsumed无法访问内部定义的widget实例。
  4. 状态管理不当:普通变量无法在React组件生命周期中保持状态,会导致闭包失效。

修复代码

1. 父组件(按钮控制逻辑)

用React状态控制Youglish组件的显示/隐藏,替代直接调用函数:

import { useState } from 'react';
import YouglishWidget from './YouglishWidget';

function YourParentComponent() {
  const [showYouglish, setShowYouglish] = useState(false);

  return (
    <div id="buttons">
      <button 
        id="youglish" 
        onClick={() => setShowYouglish(true)} 
        style={{ display: showYouglish ? 'none' : 'block'}}
      >
        YouGlish
      </button>
      {/* 条件渲染Youglish组件 */}
      {showYouglish && <YouglishWidget />}
    </div>
  );
}

2. YouglishWidget组件(核心修复)

使用React Hooks处理脚本加载、API初始化和状态管理:

import { useEffect, useRef } from 'react';

export default function YouglishWidget() {
  // 用useRef保存widget实例和状态,避免闭包问题
  const widgetRef = useRef(null);
  const viewsRef = useRef(0);
  const curTrackRef = useRef(0);
  const totalTracksRef = useRef(0);

  useEffect(() => {
    // 检查YouGlish API是否已加载,避免重复插入脚本
    if (window.YG) {
      initWidget();
      return;
    }

    // 动态加载Youglish脚本
    const tag = document.createElement('script');
    tag.src = "https://youglish.com/public/emb/widget.js";
    // 脚本加载完成后初始化组件
    tag.onload = initWidget;
    const firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    // 组件卸载时清理全局回调
    return () => {
      if (window.onYouglishAPIReady) {
        delete window.onYouglishAPIReady;
      }
    };
  }, []);

  // 初始化Youglish Widget
  function initWidget() {
    const widget = new YG.Widget("widget-1", {
      width: 640,
      components: 9,
      events: {
        onFetchDone: onFetchDone,
        onVideoChange: onVideoChange,
        // 传入widget实例解决作用域问题
        onCaptionConsumed: () => onCaptionConsumed(widget),
      },
    });

    widget.fetch("courage", "english");
    widgetRef.current = widget;
  }

  function onFetchDone(event) {
    if (event.totalResult === 0) {
      alert("No result found");
    } else {
      totalTracksRef.current = event.totalResult;
    }
  }

  function onVideoChange(event) {
    curTrackRef.current = event.trackNumber;
    viewsRef.current = 0;
  }

  function onCaptionConsumed(widget) {
    if (++viewsRef.current < 3) {
      widget.replay();
    } else if (curTrackRef.current < totalTracksRef.current) {
      widget.next();
    }
  }

  return <div id="widget-1"></div>;
}

关键修复点说明

  • 条件渲染组件:通过useState控制组件的挂载/卸载,符合React的渲染机制。
  • 脚本加载优化:检查全局window.YG避免重复加载脚本,提升性能并防止冲突。
  • 作用域修复:用useRef保存状态和实例,解决闭包导致的变量失效问题;将widget实例直接传入回调函数。
  • 生命周期管理:使用useEffect处理脚本加载和清理,确保组件卸载时不会遗留全局变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:50:17