I'm about two weeks into studying React and working on my first SPA. I'm loving react and able to figure out many of my problems but I've run into two problems on this MusicPlayer ponent I'm making.
One is that when I change src in my html audio element the actual audio doesn't change even though the src path does change. I can see it happening in dev tools. I can see the src change when a button is clicked, but the audio that is playing doesn't change. If the audio track finishes it doesn't load the next track. The audio that I hear is always track 1 regardless of what the src is.
My other issue is that songBuilder() is returning undefined. I can't find any bugs in my syntax though they must be there. I used create-react-app as my boilerplate as I don't understand webpack in the slightest yet. Is my map problem a deficit in my JS understanding or is something odd happening with the bundling/build? Please let me know if more information is needed to answer this question. Thank you!
import React, { Component } from "react";
const songRepo = [
{
title: "The Silver Swan",
songLength: "0:13",
path: require("./songs/thesilverswan.mp3")
},
{
title: "Miracle Cure",
songLength: "0:12",
path: require("./songs/miraclecure.mp3")
},
{
title: "Miracle Cure",
songLength: "0:12",
path: require("./songs/miraclecure.mp3")
},
{
title: "Miracle Cure",
songLength: "0:12",
path: require("./songs/miraclecure.mp3")
}
];
export default class MusicPlayer extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
songBuilder() {
return songRepo.map((song, index) => (
<li
className={index % 2 === 0 ? "even song_wrapper" : "odd song_wrapper"}
>
<span className="song_number"> {index + 1}</span>
<span key={index + 1} className="song_title">
{song.title}
</span>
<span className="song_length">{song.songLength}</span>
</li>
));
}
playerClick(type) {
if (type === "next_song" && this.state.count < songRepo.length - 1) {
this.setState({ count: this.state.count + 1 });
} else if (type === "prev_song" && this.state.count > 0) {
this.setState({ count: this.state.count - 1 });
}
}
render() {
return (
<div className="player">
<div className="player_nav">
<div className="player_title">
<span className="song_number">{this.state.count + 1}</span>
<span className="song_title">
{songRepo[this.state.count].title}
</span>
<span className="song_length">
{songRepo[this.state.count].songLength}
</span>
</div>
<audio className="waveform" controls="controls">
<source src={songRepo[this.state.count].path} type="audio/mp3" />
</audio>
<div className="player_buttons">
<span
className="prev_song"
onClick={this.playerClick.bind(this, "prev_song")}
>
‹‹
</span>
<span> </span>
<span
className="next_song"
onClick={this.playerClick.bind(this, "next_song")}
>
››
</span>
</div>
<div>
<ul className="song_list">{songBuilder()}</ul>
</div>
</div>
</div>
);
}
}
I'm about two weeks into studying React and working on my first SPA. I'm loving react and able to figure out many of my problems but I've run into two problems on this MusicPlayer ponent I'm making.
One is that when I change src in my html audio element the actual audio doesn't change even though the src path does change. I can see it happening in dev tools. I can see the src change when a button is clicked, but the audio that is playing doesn't change. If the audio track finishes it doesn't load the next track. The audio that I hear is always track 1 regardless of what the src is.
My other issue is that songBuilder() is returning undefined. I can't find any bugs in my syntax though they must be there. I used create-react-app as my boilerplate as I don't understand webpack in the slightest yet. Is my map problem a deficit in my JS understanding or is something odd happening with the bundling/build? Please let me know if more information is needed to answer this question. Thank you!
import React, { Component } from "react";
const songRepo = [
{
title: "The Silver Swan",
songLength: "0:13",
path: require("./songs/thesilverswan.mp3")
},
{
title: "Miracle Cure",
songLength: "0:12",
path: require("./songs/miraclecure.mp3")
},
{
title: "Miracle Cure",
songLength: "0:12",
path: require("./songs/miraclecure.mp3")
},
{
title: "Miracle Cure",
songLength: "0:12",
path: require("./songs/miraclecure.mp3")
}
];
export default class MusicPlayer extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
songBuilder() {
return songRepo.map((song, index) => (
<li
className={index % 2 === 0 ? "even song_wrapper" : "odd song_wrapper"}
>
<span className="song_number"> {index + 1}</span>
<span key={index + 1} className="song_title">
{song.title}
</span>
<span className="song_length">{song.songLength}</span>
</li>
));
}
playerClick(type) {
if (type === "next_song" && this.state.count < songRepo.length - 1) {
this.setState({ count: this.state.count + 1 });
} else if (type === "prev_song" && this.state.count > 0) {
this.setState({ count: this.state.count - 1 });
}
}
render() {
return (
<div className="player">
<div className="player_nav">
<div className="player_title">
<span className="song_number">{this.state.count + 1}</span>
<span className="song_title">
{songRepo[this.state.count].title}
</span>
<span className="song_length">
{songRepo[this.state.count].songLength}
</span>
</div>
<audio className="waveform" controls="controls">
<source src={songRepo[this.state.count].path} type="audio/mp3" />
</audio>
<div className="player_buttons">
<span
className="prev_song"
onClick={this.playerClick.bind(this, "prev_song")}
>
‹‹
</span>
<span> </span>
<span
className="next_song"
onClick={this.playerClick.bind(this, "next_song")}
>
››
</span>
</div>
<div>
<ul className="song_list">{songBuilder()}</ul>
</div>
</div>
</div>
);
}
}
Share
Improve this question
edited Sep 13, 2017 at 6:48
TJK
asked Sep 13, 2017 at 6:24
TJKTJK
551 silver badge7 bronze badges
4
- which function gives undefined? – Vikram Saini Commented Sep 13, 2017 at 6:27
- @VikramSaini "My other issue is that songBuilder() is returning undefined" – Suraj Rao Commented Sep 13, 2017 at 6:28
- songBuilder() is invoked towards the bottom nested in a <ul /> – TJK Commented Sep 13, 2017 at 6:29
-
1
Use
this.songBuilder()
instead ofsongBuilder()
to refer to the member function of your class. – jlaitio Commented Sep 13, 2017 at 6:32
1 Answer
Reset to default 5try to call this method as
<ul className="song_list">{this.songBuilder}</ul>
initially you called your method as
songBuilder()--returns "undefined" since this points to the window
this.songBuilder--works as this point to current object
If your function is defined within an object, calling it directly from an object will set its context to the object on which the function is being called.