next.js React在事件中使用钩子

laik7k3q  于 2023-10-18  发布在  React
关注(0)|答案(1)|浏览(126)

我创建了以下钩子来在react中播放音频:

"use client";

import { useEffect, useState } from "react";

export const 

useAudio = (url: string) => {
  const [audio, setAudio] = useState<HTMLAudioElement | null>(null);
  const [playing, setPlaying] = useState(false);

  const setVolume = (volume: number) => {
    if (audio) audio.volume = volume;
    console.log(audio);
  };

  const toggle = () => {
    setPlaying(!playing);
    console.log(audio);
  };

  useEffect(() => {
    playing ? audio?.play() : audio?.pause();
  }, [playing]);

  useEffect(() => {
    audio?.addEventListener("ended", () => audio?.play());
  }, [audio]);

  useEffect(() => {
    setAudio(new Audio(url));
    return () => {
      audio?.removeEventListener("ended", () => audio.play());
    };
  }, []);

  return { playing, toggle, setVolume };
};

当我在toggle函数中控制台记录audio元素时,我得到了正确的元素,但在setVolume中它总是null。
我在一个事件管理器鼠标中设置音量,像这样移动:

document.addEventListener("mousemove", function (e) {
      let element = document.getElementById("follow");
      let left = e.pageX;
      let top = e.pageY;
      element!.style.left = left + "px";
      element!.style.top = top + "px";

      const distance = Math.sqrt(
        Math.pow(left - devPosition.current.x, 2) +
          Math.pow(top - devPosition.current.y, 2)
      );

      setVolume(1 - distance / diagonal.current);
    });

这会因为我在这样的侦听器中调用setVolume而发生吗?如果是这样,我能做些什么呢?

hts6caw3

hts6caw31#

我试过你的useAudio钩子,我认为钩子没有什么问题。
例如,像这样的组件按预期工作,不会产生任何错误。

"use client";

import { useEffect } from "react";
import { useAudio } from "./audioHook"

export default function Home() {
  const controls = useAudio('./horse.mp3');

  useEffect(() => {
    console.log(controls.playing);
  }, [controls]);

  const workWithAudio = () => {
    controls.toggle();
  };

  const changeVolume = () => {
    controls.setVolume(0.2);
  };
  
  return (
    <main>
      <button onClick={workWithAudio}>
        The toggle button
      </button>
      <button onClick={changeVolume}>
        The volume button
      </button>
    </main>
  )
}

您处理侦听器的方式可能存在问题。如果我理解正确的话(例如看这里How to add a 'mousemove' event listener to a component Cursor which is moved with the cursor pointer in ReactJS?),在React组件中添加侦听器的首选方法是将其添加到DOM节点,如下所示:

"use client";

import { useAudio } from "./audioHook"

export default function Home() {
  const controls = useAudio('./horse.mp3');

  const handleMouseMove = (e: MouseEvent) => {
    let element = document.getElementById("follow");
    let left = e.pageX;
    let top = e.pageY;
    element!.style.left = left + "px";
    element!.style.top = top + "px";

    // const distance = Math.sqrt(
    //   Math.pow(left - devPosition.current.x, 2) +
    //     Math.pow(top - devPosition.current.y, 2)
    // );

    controls.setVolume(0.5);
  }

  return (
    <main onMouseMove={handleMouseMove}>
      <div id="follow">TEST</div>
    </main>
  )
}

我不能访问你在函数中使用的devPositiondiagonal变量,所以我必须使用一个常量,但是如果你以这种方式示例化监听器,你就可以毫无问题地设置音量。

相关问题