Day 1 with React and I'm not seeing a way to get the < button> onClick={this.props.handleClickPlay}>Play < /button> to play audio. If I move it under {audioListNodes} the button works fine. I'd like to have each link play a separate audio file eventually but for right now just playing the same file is a win, but moving the event handler into the list kills it. I'm assuming it's because THIS is no longer referencing AudioList but rather var data? Once I have the button firing how do I ID which button was clicked and change the AudioObject source?
var data = [
{voice: "Drew", file:"Drew.mp3", volume: 90},
{voice: "Chris", file:"Chris.mp3", volume: 85},
{voice: "Patrick", file:"Patrick.mp3", volume: 85},
{voice: "Everett", file:"Everett.mp3", volume: 60},
];
var AudioList = React.createClass({
render: function() {
var audioListNodes = this.props.data.map(function(el, index) {
return (
<div author={el.voice}>
{el.file}
<button onClick={this.props.handleClickPlay}>Play</button>
</div>
);
});
return (
<div className="audioList">
{audioListNodes}
</div>
);
}
});
var AudioObject = React.createClass({
play: function () {
var audio = this.getDOMNode();
audio.load();
audio.play();
},
render: function() {
return (
<audio preload="auto" controls="true" autoPlay="">
<source src='female/DeDe Splaingard.mp3'></source>
Your browser does not support audio.
</audio>
);
}
});
var App = React.createClass({
handleClickPlay: function() {
this.refs.audioObject.play()
},
render: function() {
return (
<div>
<AudioObject ref="audioObject" />
<AudioList data={this.props.data} handleClickPlay={this.handleClickPlay} />
</div>
);
}
});
ReactDOM.render(
<App data={data} />,
document.getElementById('content')
);
You have to bind(this)
to the anonymous function since the context inside of .map
changes:
var audioListNodes = this.props.data.map(function(el, index) {
return (
<div author={el.voice}>
{el.file}
<button onClick={this.props.handleClickPlay}>Play</button>
</div>
);
}.bind(this));
Another option is to start using ES6 arrow functions, which lexically pass this
:
var audioListNodes = this.props.data.map((el, index) => {
return (
<div author={el.voice}>
{el.file}
<button onClick={this.props.handleClickPlay}>Play</button>
</div>
);
});
As @Henrik Andersson mentioned in the comments, you can also pass this
directly to map
.
var audioListNodes = this.props.data.map(function(el, index) {
return (
<div author={el.voice}>
{el.file}
<button onClick={this.props.handleClickPlay}>Play</button>
</div>
);
}, this);
You should add this to .map(), because inside of .map() this refers to window or undefined when in strict mode.
var audioListNodes = this.props.data.map(function(el, index) {
return (
<div author={el.voice}>
{el.file}
<button onClick={this.props.handleClickPlay}>Play</button>
</div>
);
}, this);
! here !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With