React 在 eventListener 中使用钩子

问题描述 投票:0回答:1

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

"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 };
};

当我在切换函数内控制台记录音频元素时,我得到了正确的元素,但在 setVolume 中它始终为 null。

我在事件监听器 mouseMove 中设置音量,如下所示:

    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 而发生这种情况?如果是这样,我该怎么办?

javascript reactjs next.js react-hooks html5-audio
1个回答
0
投票

您直接设置

audio.volume
,但您需要使用
setAudio
功能,尝试这样的操作:

const setVolume = (volume: number) => {
    if (audio) {
        setAudio(p => ({ ...p, volume }))
    }
};

请记住,

console.log
后面的
setAudio
不会立即显示您的更改:
useState set 方法没有立即反映更改

© www.soinside.com 2019 - 2024. All rights reserved.