如何在播放列表中使用 ReactHowler
How to use ReactHowler with a playlist
我正在从外部来源获取播放列表 JSON object,其中包含曲目标题,还包含音频文件的 URL。我将此 object 映射到带有 <ul>
的 <li>
元素,但我无法让它工作。我安装了 Howler 和 HowlerReact,但在页面加载时出现以下错误:
- TypeError: 无法读取未定义的 属性 'length'
- Howl.playing
- node_modules/howler/dist/howler.js:1691
这是我的代码:
import React, { useState } from 'react';
import ReactHowler from 'react-howler'
import Async from 'react-async';
const loadTracks = () =>
fetch('...')
.then(res => (res.ok ? res : Promise.reject(res)))
.then(res => res.json());
const Music = () => {
const [ play, setPlay ] = useState({
currentTrack: null,
play: false
});
return (
<ul className="music">
<ReactHowler src={currentTrack} playing={play} />
<Async promiseFn={loadTracks}>
<Async.Loading>Loading...</Async.Loading>
<Async.Fulfilled>
{data => {
return (
Object.keys(data[title].tracks).map(track => {console.log(data[title].tracks);
return(
<li key={data[title].tracks[track].filename}>
<button
data-permalink={data[title].tracks[track].title}
onClick={() => setPlay({currentTrack: data[title].tracks[track].filename, play: !play})}>
{data[title].tracks[track].title}
</button>
</li>
)})
)
}}
</Async.Fulfilled>
<Async.Rejected>
{error => `Something went wrong: ${error.message}`}
</Async.Rejected>
</Async>
</ul>
);
}
export default Music;
我对React函数式组件还不太熟悉,基本了解,但不知道怎么和音频播放器等结合起来。
我不是特别喜欢 Howler,所以欢迎任何关于如何让它工作的建议。
我使用普通 HTML5 音频元素,不需要 Howler:
import React, { useState, useEffect, useRef } from 'react';
import Async from 'react-async';
function countDown(duration, time) {
if (!isNaN(time)) {
var timeLeft = duration - time;
return (
Math.floor(timeLeft / 60) + ":" + ("0" + Math.floor(timeLeft % 60)).slice(-2)
);
}
}
const loadTracks = () =>
fetch('...')
.then(res => (res.ok ? res : Promise.reject(res)))
.then(res => res.json());
const Music = () => {
const player = useRef(null);
const [ state, setState ] = useState({
currentTrack: null,
currentTime: null,
duration: null
});
let currentTime = getTime(state.currentTime);
let duration = getTime(state.duration);
let timeLeft = countDown(state.duration, state.currentTime);
let currentTrack = null;
useEffect(() => {
if (state.currentTrack) {
player.current.src = state.currentTrack;
player.current.play();
}
player.current.addEventListener('timeupdate', e => {
setState(prevState => ({
currentTime: e.target.currentTime,
duration: e.target.duration,
currentTrack: prevState.currentTrack
}));
});
return function cleanup() {
player.current.removeEventListener('timeupdate', () => {});
}
}, [state.currentTrack]);
return (
<ul className="music">
<Async promiseFn={loadTracks}>
<Async.Loading>Loading...</Async.Loading>
<Async.Fulfilled>
{data => {
return (
Object.keys(data[title].tracks).map(track => {console.log(data[title].tracks);
return(
<li key={data[title].tracks[track].filename}>
<button
data-permalink={data[title].tracks[track].title}
onClick={() => setState({currentTrack: data[title].tracks[track].filename})}>
{data[title].tracks[track].title}
</button>
</li>
)})
)
}}
</Async.Fulfilled>
<Async.Rejected>
{error => `Something went wrong: ${error.message}`}
</Async.Rejected>
</Async>
</ul>
);
}
export default Music;
我正在从外部来源获取播放列表 JSON object,其中包含曲目标题,还包含音频文件的 URL。我将此 object 映射到带有 <ul>
的 <li>
元素,但我无法让它工作。我安装了 Howler 和 HowlerReact,但在页面加载时出现以下错误:
- TypeError: 无法读取未定义的 属性 'length'
- Howl.playing
- node_modules/howler/dist/howler.js:1691
这是我的代码:
import React, { useState } from 'react';
import ReactHowler from 'react-howler'
import Async from 'react-async';
const loadTracks = () =>
fetch('...')
.then(res => (res.ok ? res : Promise.reject(res)))
.then(res => res.json());
const Music = () => {
const [ play, setPlay ] = useState({
currentTrack: null,
play: false
});
return (
<ul className="music">
<ReactHowler src={currentTrack} playing={play} />
<Async promiseFn={loadTracks}>
<Async.Loading>Loading...</Async.Loading>
<Async.Fulfilled>
{data => {
return (
Object.keys(data[title].tracks).map(track => {console.log(data[title].tracks);
return(
<li key={data[title].tracks[track].filename}>
<button
data-permalink={data[title].tracks[track].title}
onClick={() => setPlay({currentTrack: data[title].tracks[track].filename, play: !play})}>
{data[title].tracks[track].title}
</button>
</li>
)})
)
}}
</Async.Fulfilled>
<Async.Rejected>
{error => `Something went wrong: ${error.message}`}
</Async.Rejected>
</Async>
</ul>
);
}
export default Music;
我对React函数式组件还不太熟悉,基本了解,但不知道怎么和音频播放器等结合起来。
我不是特别喜欢 Howler,所以欢迎任何关于如何让它工作的建议。
我使用普通 HTML5 音频元素,不需要 Howler:
import React, { useState, useEffect, useRef } from 'react';
import Async from 'react-async';
function countDown(duration, time) {
if (!isNaN(time)) {
var timeLeft = duration - time;
return (
Math.floor(timeLeft / 60) + ":" + ("0" + Math.floor(timeLeft % 60)).slice(-2)
);
}
}
const loadTracks = () =>
fetch('...')
.then(res => (res.ok ? res : Promise.reject(res)))
.then(res => res.json());
const Music = () => {
const player = useRef(null);
const [ state, setState ] = useState({
currentTrack: null,
currentTime: null,
duration: null
});
let currentTime = getTime(state.currentTime);
let duration = getTime(state.duration);
let timeLeft = countDown(state.duration, state.currentTime);
let currentTrack = null;
useEffect(() => {
if (state.currentTrack) {
player.current.src = state.currentTrack;
player.current.play();
}
player.current.addEventListener('timeupdate', e => {
setState(prevState => ({
currentTime: e.target.currentTime,
duration: e.target.duration,
currentTrack: prevState.currentTrack
}));
});
return function cleanup() {
player.current.removeEventListener('timeupdate', () => {});
}
}, [state.currentTrack]);
return (
<ul className="music">
<Async promiseFn={loadTracks}>
<Async.Loading>Loading...</Async.Loading>
<Async.Fulfilled>
{data => {
return (
Object.keys(data[title].tracks).map(track => {console.log(data[title].tracks);
return(
<li key={data[title].tracks[track].filename}>
<button
data-permalink={data[title].tracks[track].title}
onClick={() => setState({currentTrack: data[title].tracks[track].filename})}>
{data[title].tracks[track].title}
</button>
</li>
)})
)
}}
</Async.Fulfilled>
<Async.Rejected>
{error => `Something went wrong: ${error.message}`}
</Async.Rejected>
</Async>
</ul>
);
}
export default Music;