繁体   English   中英

如何使用 React 功能组件解决“HTMLMediaElement 之前已连接到不同的 MediaElementSourceNode”问题

[英]How can I solve "HTMLMediaElement already connected previously to a different MediaElementSourceNode" problem using React functional component

我在使用 create-react-app 创建的应用程序中使用 React 功能组件,因此会自动启用React.StrictMode 我不想禁用它,因为它可以帮助我发现正在开发的潜在问题。 麻烦的是它使组件渲染两次,这会产生错误:
未捕获的 DOMException:无法在“AudioContext”上执行“createMediaElementSource”:HTMLMediaElement 之前已经连接到不同的 MediaElementSourceNode ,因为 HTMLMediaElement 在第一次渲染中连接。 我想知道,有没有办法将 HTMLMediaElement 与以前的 MediaElementSourceNode 断开连接......也许将其设置为null或其他东西,以便它可以获得新的连接?
下面是我的引发错误的代码:

import React, { useEffect, useRef } from "react";

const Canvas = () => {
  const audioRef = useRef(null);
  const filUploadRef = useRef(null);
  const canvasRef = useRef(null);

  let audioSource;
  let analyser;
  let dataArray;

  useEffect(() => {
    const audioElement = audioRef.current;
    const canvas = canvasRef.current;
    const fileUploadField = filUploadRef.current;

    fileUploadField.addEventListener("change", () => {
      const audioContext = new AudioContext();

      const files = fileUploadField.files;
      audioElement.src = URL.createObjectURL(files[0]);
      audioElement.load();
      audioElement.play();

      audioSource = audioContext.createMediaElementSource(audioElement);
      analyser = audioContext.createAnalyser();
      audioSource.connect(analyser);
      analyser.connect(audioContext.destination);
      dataArray = new Uint8Array(analyser.frequencyBinCount);
    });
  }, []);

  const handleTogglePlayPause = () => {
    //TODO: Implement toggle Play/Pause when the button is clicked.
  };

  return (
    <>
      <canvas ref={canvasRef} />
      <audio controls ref={audioRef} />
      <input type="file" id="file-upload" accept="audio/*" ref={filUploadRef} />
      <button onClick={handleTogglePlayPause} type="button">
        {/* ^ This button element is related to handleTogglePlayPause function for a different stage*/}
        Play/Pause
      </button>
    </>
  );
};

export default Canvas;

您可以检查audioSource是否已经有源,如果有,您可以尝试避免创建新的媒体元素源。 此外,您无需创建新的分析器并连接它。

将此 if 检查添加到您的代码中,它应该可以解决问题。

// ..
audioElement.play();

if (!audioSource) {
    audioSource = audioContext.createMediaElementSource(audioElement);
    analyser = audioContext.createAnalyser();
    audioSource.connect(analyser);
    analyser.connect(audioContext.destination);
}
//..

好吧,react strict 模式有助于识别问题,但同时它也会产生新问题。 因此,您可能会考虑完全关闭严格模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM