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

React中<audio>组件无法从指定时间播放的问题求助

React音频从指定时间点播放问题修复

你的问题核心在于:组件初始挂载时yesChecker为false,<audio>元素还没被渲染,导致你写的空依赖useEffect无法获取到有效的audioRef,自然没法设置播放起始时间。而且当yesChecker变为true后,这个空依赖的useEffect也不会重新执行,所以音频始终从0秒开始。

修复方案:

调整useEffect的依赖项,让它在yesChecker变为true时触发,同时处理音频加载状态,确保设置currentTime时音频元数据已加载完成。

修改后的代码:

import { useState, useEffect, useRef } from "react";
import "./App.css";
import audioFile from "./assets/Everybody.mp3";

export default function App() {
  const [noIdx, setNoIdx] = useState(0);
  const [yesChecker, setYesChecker] = useState(false);
  const yesSize = noIdx * 20 + 16;

  const audioRef = useRef<HTMLAudioElement | null>(null);

  // ... 其他代码保持不变

  // 调整后的useEffect,依赖yesChecker
  useEffect(() => {
    // 只有当yesChecker为true且audio元素存在时才执行
    if (!yesChecker || !audioRef.current) return;

    const audio = audioRef.current;

    // 处理音频播放的逻辑
    const startAudioAt13s = () => {
      audio.currentTime = 13;
      // 处理浏览器自动播放限制,需要catch错误
      audio.play().catch(err => {
        console.error("音频播放失败:", err);
      });
    };

    // 如果音频已经加载了元数据,直接执行
    if (audio.readyState >= 2) { // HAVE_CURRENT_DATA 状态表示已获取到足够的元数据
      startAudioAt13s();
    } else {
      // 否则监听loadedmetadata事件,加载完成后执行
      audio.addEventListener("loadedmetadata", startAudioAt13s);
    }

    // 清理函数,移除事件监听
    return () => {
      audio.removeEventListener("loadedmetadata", startAudioAt13s);
    };
  }, [yesChecker]); // 依赖yesChecker,状态变化时重新执行

  const handleNoClick = () => {
    setNoIdx(noIdx + 1);
    createHeart();

    const noText = getNoText();
    if (noText === "está bien") {
      setYesChecker(true);
    }
  };

  // ... 其他代码保持不变

  return (
    <div className="flex flex-col items-center justify-center">
      {yesChecker ? (
        <>
          <div className="flex flex-col items-center">
            <img
              className="h-[300px] mx-auto"
              src="https://media.tenor.com/BNcELzaiMDkAAAAi/happy-valentines-day-my-love.gif"
              alt="Happy Valentine's Day"
            />
            {/* 移除autoPlay,由代码控制播放 */}
            <audio ref={audioRef} src={audioFile} />
            <h1 className="text-4xl my-4 text-center"> XFIN! :3</h1>
          </div>
        </>
      ) : (
        // ... 原来的其他内容
      )}
    </div>
  );
}

关键改动说明:

  1. 更新useEffect依赖:加入yesChecker,确保当状态变为true时,代码能触发执行,此时<audio>元素已经渲染到DOM中,audioRef能获取到有效实例。
  2. 移除autoPlay属性:避免浏览器自动从0秒开始播放,完全由代码控制播放时机和起始位置。
  3. 判断音频加载状态:直接检查readyState,如果音频已经加载完成,无需等待loadedmetadata事件,提升响应速度。
  4. 处理播放错误:调用play()时添加catch,处理浏览器的自动播放限制(比如用户未交互时无法自动播放的情况)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:00:36