javascript - React js:音频元素 src 正在 setState 上更新,但 audioRef 没有
问题描述
请帮我!我正在使用上下文 API 将曲目传递给 MucsicPlayer。但每当我设置setTracks
状态音频元素 src 更新<audio preload="auto" src="001.mp3">
但 audioRef.current 不更新。我检查了一下,看到了audioRef.current = <audio preload="auto" src(unknown)>
。所以 ref src 不会更新。我应该怎么办。并且您能否给我一些想法,以便在 setTracks 状态更改时自动播放音频。
import React, { useState, useEffect, useRef, useContext } from 'react'
import { TrackContext } from '../../music/TrackContext'
const MusicPlayer = () => {
const [tracks, setTracks] = useContext(TrackContext)
console.log(tracks)
// states
const [trackIndex, setTrackIndex] = useState(0)
console.log(trackIndex)
const [trackProgress, setTrackProgress] = useState(0)
const [isPlaying, setIsPlaying] = useState(false)
// eslint-disable-next-line
const [volume, setVolume] = useState(1)
const { title, artist, image, audioSrc } = tracks[trackIndex]
//refs
const audio = new Audio(audioSrc)
const audioRef = useRef(audio)
const intervalRef = useRef()
const isReady = useRef(false)
console.log(audioRef.current)
const { duration } = audioRef.current
const toPrevTrack = () => {
if (trackIndex - 1 < 0) {
setTrackIndex(tracks.length - 1)
} else {
setTrackIndex(trackIndex - 1)
}
}
const toNextTrack = () => {
if (trackIndex < tracks.length - 1) {
setTrackIndex(trackIndex + 1)
} else {
setTrackIndex(0)
}
}
const startTimer = () => {
clearInterval(intervalRef.current)
intervalRef.current = setInterval(() => {
if (audioRef.current.ended) {
toNextTrack()
} else {
setTrackProgress(audioRef.current.currentTime);
}
}, [1000])
}
useEffect(() => {
if (isPlaying) {
audioRef.current.play()
startTimer();
} else {
clearInterval(intervalRef.current)
audioRef.current.pause()
}
// eslint-disable-next-line
}, [isPlaying])
useEffect(() => {
return () => {
audioRef.current.pause()
clearInterval(intervalRef.current)
}
}, [])
useEffect(() => {
audioRef.current.play()
audioRef.current = new Audio(audioSrc)
setTrackProgress(audioRef.current.currentTime)
if (isReady.current) {
audioRef.current.play()
setIsPlaying(true)
startTimer()
} else {
isReady.current = true
}
// eslint-disable-next-line
}, [trackIndex])
const onScrub = (value) => {
clearInterval(intervalRef.current)
audioRef.current.currentTime = value
setTrackProgress(audioRef.current.currentTime)
}
const onScrubEnd = () => {
if (!isPlaying) {
setIsPlaying(true);
}
startTimer();
}
const onScrubVolume = (value) => {
audioRef.current.volume = value
setVolume(audioRef.current.value)
}
function formatMinutes(sec) {
return new Date(sec * 1000).toUTCString().split(" ")[4].substr(3, 8)
}
const currentPercentage = duration ? `${(trackProgress / duration) * 100}%` : '0%';
const trackStyling = `-webkit-gradient(linear, 0% 0%, 100% 0%, color-stop(${currentPercentage}, #fff), color-stop(${currentPercentage}, #777))`;
return (
<div className="player">
<div className="left-block">
<div className="art">
<img src={image} alt="" />
</div>
<div className="song-details">
<div className="song-name">{title}</div>
<div className="artist-name">
<a href="sa">{artist}</a>
</div>
</div>
</div>
<div className="center-block">
<div className="song-progress">
<div>{formatMinutes(audioRef.current.currentTime)}</div>
<input
value={trackProgress}
step="1"
min="1"
max={duration ? duration : `${duration}`}
onChange={(e) => onScrub(e.target.value)}
onMouseUp={onScrubEnd}
onKeyUp={onScrubEnd}
style={{ background: trackStyling }}
type="range" />
<div>{duration ? formatMinutes(duration) : "00:00"}</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default MusicPlayer
解决方案
推荐阅读
- regex - 如何为此制作正则表达式?
- ios - 如何检查segue是否正在进行
- python - 向上舍入到某个数字
- delphi - 在 firemonkey 中打开并读取文件
- amazon-web-services - Amazon S3 文件夹级别权限存储桶策略 NOT IAM
- python - 行代码返回带有打开文件的语法错误
- javascript - 图像上传到 cloudinary 仅在第一次尝试时有效,然后虽然文件已满但显示“空文件”
- c - 为什么键盘中断在 QEMU 中有效,但在真实硬件上无效?
- jekyll - 无法从 Jekyll 中的 sass 文件导入变量
- python - 为自定义 CGAL 函数构建 Python 接口