Попытка использовать React useRef в массиве, чтобы получить продолжительность аудио
Я получаю сообщение об ошибке 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
Спасибо заранее
1 ответ
Решение
У вас есть дополнительная итерация, которая содержит 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;