如何对多个元素使用一个useRef?或者如何将useRef用于类似行为?

时间:2019-12-22 22:40:32

标签: reactjs react-hooks

我有多个按钮,单击它们会触发另一个音频文件。

我设法使每个按钮使用不同的useRef来使其正常工作,但我想有一种更好的方法来实现此目的:

const App = () => {

  const myAudio1 = useRef()
  const myAudio2 = useRef()
  const myAudio3 = useRef()

  const handleAudio1 = () => {
    myAudio1.current.play()
  }

  const handleAudio2 = () => {
    myAudio2.current.play()
  }

  const handleAudio3 = () => {
    myAudio3.current.play()
  }

  return (
    <div id="drum-machine">
      <div onClick={() => handleAudio1()} id="Btn1">
        <div> Button 1
          <audio ref={myAudio1}>
            <source id="Btn1" src="drumSounds/sound1.wav" type="audio/mpeg"/>
          </audio>
        </div>
      </div>

      <div onClick={() => handleAudio2()} id="Btn2">
        <div> Button 2
          <audio ref={myAudio2}>
             <source id="Btn2" src="drumSounds/sound2.wav" type="audio/mpeg"/>
          </audio>
        </div>
       </div>

       <div onClick={() => handleAudio3()} id="Btn3">
         <div> Button 3
           <audio ref={myAudio3}>
              <source id="Btn3" src="drumSounds/sound3.wav" type="audio/mpeg"/>
           </audio>
         </div>
       </div>
     </div>
   )
}

1 个答案:

答案 0 :(得分:1)

您不能在循环中使用React Hooks,但是可以将使用useRef的代码封装到其自己的组件中,然后为每个音频源呈现该组件。例如:

const AudioSource = ({ children, src, encoding = "audio/mpeg" }) => {
  const ref = React.useRef();
  const onClick = React.useCallback(() => {
    if (ref.current === undefined) {
      return;
    }

    ref.current.play();
  }, []);

  return (
    <div onClick={onClick}>
      {children}
      <audio ref={ref}>
        <source src={src} type={encoding} />
      </audio>
    </div>
  );
};

然后可以这样称呼它:

const App = () => {
  const sources = [
    {
      id: "Btn1",
      text: "Button 1",
      source: "drumSounds/sound1.wav"
    },
    {
      id: "Btn2",
      text: "Button 2",
      source: "drumSounds/sound2.wav"
    },
    {
      id: "Btn3",
      text: "Button 3",
      source: "drumSounds/sound3.wav"
    }
  ];

  return (
    <div id="drum-machine">
      {sources.map(audioSource => (
        <div key={audioSource.id} id={audioSource.id}>
          <AudioSource src={audioSource.src}>{audioSource.text}</AudioSource>
        </div>
      ))}
    </div>
  );
};