我在Create React App引导的项目的src文件夹中添加了mp3。我为音频文件Audio.js添加了一个组件,我希望根据道具https://graph.microsoft.com/v1.0/groups/[GroupID]/threads/[ConversationID]/posts
是否正确来有条件地播放该组件。
父App.js将道具传递给子Timer.js,后者呈现Audio.js。
Audio.js文件为我定义了“反应”,但从未使用过错误,我不确定为什么。
Audio.js:
playAlarm
在Timer.js中,音频呈现如下:import React, { Component } from 'react';
class Audio extends Component {
constructor() {
super();
this.url = "./chime.mp3";
this.audio = new Audio(this.url);
}
render() {
return (
this.audio
);
}
}
export default Audio;
当我测试播放音频时,当playAlarm设置为true时,我得到Uncaught RangeError:在Audio.js中,与super()所在的行超过了最大调用堆栈大小。
App.js:
{props.playAlarm ? <Audio /> : null}
导出默认应用;
这也是Timer.js:
import React, { Component } from 'react';
import Timer from './Timer';
class App extends Component {
// ES6 class property/class field syntax allows you to remove constructor when just being used to initialize state
state = {
sessionDuration: 5, // TODO: change back to 1500 when testing done
breakDuration: 3, // TODO: change back to 300 when testing done
sessionTimeRemaining: 5, // TODO: change back to 1500 when testing done
breakTimeRemaining: 3, // TODO: change back to 300 when testing done
isSession: true,
timerOn: false,
sessionNumber: 0,
playAlarm: false
}
// Using property initializer syntax to avoid need to bind, since arrow functions don't create their own this context and use value of enclosing context instead. transform-class-properties Babel plugin necessary to use this syntax (included in Create React App). Refer to https://itnext.io/property-initializers-what-why-and-how-to-use-it-5615210474a3 for more details
// DURATION CHANGES
decreaseBreakDuration = () => {
// Conditional statement prevents decrease when break is at 1 minute
if (this.state.breakDuration === 60) {
return undefined;
} else {
this.setState({
breakDuration: this.state.breakDuration - 60
});
}
}
increaseBreakDuration = () => {
this.setState({
breakDuration: this.state.breakDuration + 60
});
}
decreaseSessionDuration = () => {
// Conditional statement prevents decrease when session is at 5 minutes
if (this.state.sessionDuration === 300) {
return undefined;
} else {
this.setState({
sessionDuration: this.state.sessionDuration - 60,
sessionTimeRemaining: this.state.sessionTimeRemaining - 60
});
}
}
increaseSessionDuration = () => {
this.setState({
sessionDuration: this.state.sessionDuration + 60,
sessionTimeRemaining: this.state.sessionTimeRemaining + 60
});
}
manageBreak = () => {
this.setState({
playAlarm: false
});
this.time = setInterval(() => {
this.setState({
breakTimeRemaining: this.state.breakTimeRemaining - 1
});
if (this.state.breakTimeRemaining === 0) {
this.handleBreakComplete();
}
}, 1000);
}
manageSession = () => {
this.setState({
playAlarm: false
});
// Every 1,000 ms (1 second), subtract 1 (a single second) from displayed sessionTimeRemaining. Assigned to this.time (scoped to entire class) in order to pass it to clearInterval() when pause button is clicked
this.time = setInterval(() => {
this.setState({
sessionTimeRemaining: this.state.sessionTimeRemaining - 1
});
if (this.state.sessionTimeRemaining === 0) {
this.handleSessionComplete();
}
}, 1000);
}
handleSessionComplete = () => {
clearInterval(this.time);
this.setState({
playAlarm: true,
sessionNumber: this.state.sessionNumber + 1
})
if (this.state.sessionNumber === 4) {
this.handlePomodoroCycleDone();
} else {
this.setState({
timerOn: false,
sessionTimeRemaining: this.state.sessionDuration,
breakTimeRemaining: this.state.breakDuration,
isSession: !this.state.isSession,
});
}
}
handlePomodoroCycleDone = () => {
// TODO: Display message in modal
console.log('Great work! You finished a pomodoro cycle (four sessions). Time to relax.')
// Change back to default values
this.setState({
isSession: true,
timerOn: false,
sessionDuration: 5, // TODO: change back to 1500
breakDuration: 3, // TODO: change back to 300 when testing done
sessionTimeRemaining: 5, // TODO: change back to 1500
});
}
handleBreakComplete = () => {
clearInterval(this.time);
this.setState({
timerOn: false,
sessionTimeRemaining: this.state.sessionDuration,
breakTimeRemaining: this.state.breakDuration,
isSession: !this.state.isSession,
playAlarm: true
});
}
// PLAY, PAUSE, RESTART BUTTONS
startTimer = () => {
this.setState({
timerOn: true,
});
if (this.state.isSession) {
this.manageSession();
} else {
this.manageBreak();
}
}
pauseTimer = () => {
// Stops setInterval's calling its (setState) callback every 1000 ms
clearInterval(this.time);
this.setState({
timerOn: false
});
}
resetTimer = () => {
// Stops setInterval's calling its (setState) callback every 1000 ms
// TODO: Display 4 unchecked circle icons again
clearInterval(this.time);
this.setState({
timerOn: false,
sessionDuration: 5, // TODO: change back to 1500
breakDuration: 3, // TODO: change back to 300 when testing done
sessionTimeRemaining: 5, // TODO: change back to 1500
breakTimeRemaining: 3, // TODO: change back to 300 when testing done
sessionNumber: 0
});
}
render() {
return (
<Timer
breakDuration={this.state.breakDuration}
sessionDuration={this.state.sessionDuration}
decreaseBreakDuration={this.decreaseBreakDuration}
increaseBreakDuration={this.increaseBreakDuration}
decreaseSessionDuration={this.decreaseSessionDuration}
increaseSessionDuration={this.increaseSessionDuration}
sessionTimeRemaining={this.state.sessionTimeRemaining}
breakTimeRemaining={this.state.breakTimeRemaining}
timerOn={this.state.timerOn}
sessionNumber={this.state.sessionNumber}
isSession={this.state.isSession}
startTimer={this.startTimer}
pauseTimer={this.pauseTimer}
resetTimer={this.resetTimer}
playAlarm={this.state.playAlarm}
/>
);
};
}
答案 0 :(得分:2)
我不了解这里发生的所有事情。但是乍一看,这是一个问题:
class Audio extends Component {
constructor() {
super();
this.url = "./chime.mp3";
this.audio = new Audio(this.url);
}
render() {
return (
this.audio
);
}
}
超出调用堆栈错误是因为您正在进入无限循环。您在Audio
内部实例化Audio
,这将使另一个Audio
对象,依此类推,直到无穷大。