尝试在数组中使用 React 的 useRef 来获取音频的持续时间

Trying to us React's useRef in an array to grab an audio' duration

当我 运行 我的反应代码时,我目前收到错误 Cannot read property 'addEventListener' of undefined。该代码旨在遍历包含音频文件的列表并获取音频持续时间。该应用程序正确呈现,但我在生命周期方面做错了。我认为。下面的代码

import React, { useRef, useEffect, useState } from "react"
import { Link } from "gatsby"

const Single = ({ name, tracks }) => {
  const [duration, setDuration] = useState([])
  const audioRef = useRef([])

  function getTrackLength(track) {
    track.addEventListener("loadedmetadata", function () {
      setDuration(track.duration)
    })
  }
  useEffect(() => {
    audioRef.current = new Array(tracks.length)
  }, [])
  useEffect(() => {
    if (audioRef.current.length !== 0) {
      for (let i = 0; i <= audioRef.current.length; i++) {
        getTrackLength(audioRef.current[i])
      }
    }
  }, [])
  return (
    <>
      <h2>{name}</h2>

      <ul>
        {tracks.map((track, i) => (
          <li key={track._id}>
            <div>
              <strong>{track.name}</strong>
              <audio
                ref={el => (audioRef.current[i] = el)}
                src={track.file}
                controls
              />
              <i>{duration}</i>
            </div>
          </li>
        ))}
      </ul>
      <Link to="/singles">Back</Link>
    </>
  )
}

export default Single

非常感谢

您有一个额外的迭代,其中包含 undefined 作为 track:

//               v not <=
for (let i = 0; i < audioRef.current.length; i++) {
  getTrackLength(audioRef.current[i]);
}

您的组件应如下所示:

const Single = ({ name, tracks }) => {
  const [duration, setDuration] = useState([]);
  const audioRef = useRef(new Array(Number(tracks.length));

  useEffect(() => {
    function getTrackLength(track) {
      track.addEventListener("loadedmetadata", function () {
        setDuration([...duration, track.duration]);
      });
    }

    for (let i = 0; i < audioRef.current.length; i++) {
        getTrackLength(audioRef.current[i]);
    }
  }, []);

  return (
    <>
      <h2>{name}</h2>
      <ul>
        {tracks.map((track, i) => (
          <li key={track._id}>
            <div>
              <strong>{track.name}</strong>
              <audio
                ref={(el) => (audioRef.current[i] = el)}
                src={track.file}
                controls
              />
              <i>{duration[i]}</i>
            </div>
          </li>
        ))}
      </ul>
      <Link to="/singles">Back</Link>
    </>
  );
};

export default Single;