慕慕森
这些测试失败的原因是因为timeLeftSeconds一旦时钟进入“中断”周期,状态就没有正确设置,反之亦然。我在下面做了必要的调整。decreaseCurrentSecond注意和方法的变化down。此外,永远不要像您在此处所做的那样尝试直接更新状态中的值 - decreaseCurrentSecond = () => this.state.timeLeftSeconds--;。这不是好的做法——为什么我不能直接修改组件的状态,真的吗?import React from "react";import ReactDOM from "react-dom";import "./style.css";/* * A simple React component */const initState = { breakLength: 0.5, sessionLength: 0.5, init: "session", // stateIndex: 0, timeLeft: undefined, timeLeftSeconds: undefined, started: false, intervalFunc: undefined};const secondsToMins = (time) => { let converted = ("0" + Math.floor(time / 60)).slice(-2) + ":" + ("0" + Math.floor(time % 60)).slice(-2); return converted;};class Clock extends React.Component { constructor(props) { super(props); this.state = initState; this.breakDecrement = this.breakDecrement.bind(this); this.breakIncrement = this.breakIncrement.bind(this); this.sessionDecrement = this.sessionDecrement.bind(this); this.sessionIncrement = this.sessionIncrement.bind(this); this.startStop = this.startStop.bind(this); this.reset = this.reset.bind(this); } componentDidMount() { let sessionSeconds = this.state.sessionLength * 60; this.setState({ timeLeftSeconds: sessionSeconds }); this.setState({ timeLeft: secondsToMins(sessionSeconds) }); } breakDecrement() { console.log("break decrement"); // decrements the breakLength and the breakSeconds // breakLength is only a number ie. 5 (does not show seconds) // breakSeconds is that nunber converted into seconds let breakLength = this.state.breakLength - 1; if (breakLength > 0 && breakLength < 61) { this.setState({ breakLength: breakLength }); // let breakSeconds = breakLength * 60; // states[1]["duration"] = breakSeconds; } } breakIncrement() { // same as decrement except does increment let breakLength = this.state.breakLength + 1; if (breakLength > 0 && breakLength < 61) { this.setState({ breakLength: breakLength }); // let breakSeconds = breakLength * 60; // states[1]["duration"] = breakSeconds; } } sessionDecrement() { // decrements the sessionLength and the sessionSeconds // sessionLength is only a number ie. 25 (does not show seconds) // sessionSeconds is that nunber converted into seconds let sessionLength = this.state.sessionLength - 1; if (sessionLength > 0 && sessionLength < 61) { // states[0]["duration"] = sessionLength * 60; this.setState((prevState) => ({ sessionLength: prevState.sessionLength - 1, timeLeftSeconds: (prevState.sessionLength - 1) * 60, timeLeft: secondsToMins((prevState.sessionLength - 1) * 60) })); } } sessionIncrement() { // same as decrement except does increment let sessionLength = this.state.sessionLength + 1; if (sessionLength > 0 && sessionLength < 61) { // states[0]["duration"] = sessionLength * 60; this.setState((prevState) => ({ sessionLength: prevState.sessionLength + 1, timeLeftSeconds: (prevState.sessionLength + 1) * 60, timeLeft: secondsToMins((prevState.sessionLength + 1) * 60) })); } } startStop(id) { // starts the countDown, which runs continuously until the start/stop button // is pressed again, which pauses the countdown. // the id parameter is used by countDown to play the audio beep if (!this.state.started) { this.setState({ started: true }); this.countDown(id); } // pauses the countDown if (this.state.started) { this.setState({ started: false }); let intervalFunc = this.state.intervalFunc; clearInterval(intervalFunc); } } reset() { let intervalFunc = this.state.intervalFunc; clearInterval(intervalFunc); // reset state to default values this.setState({ breakLength: 5 }); this.setState({ sessionLength: 25 }); this.setState({ init: "session" }); this.setState({ timeLeftSeconds: 1500 }); this.setState({ timeLeft: "25:00" }); // this.setState({ stateIndex: 0 }); this.setState({ started: false }); this.setState({ intervalFunc: undefined }); } decreaseCurrentSecond = () => //this.state.timeLeftSeconds--; { this.setState({ timeLeftSeconds: this.state.timeLeftSeconds - 1 }); return this.state.timeLeftSeconds; }; countDown(id) { // set the function to a variable and set state to it, so the function // can be paused with clearInterval() var intervalFunc = setInterval( () => down(this.decreaseCurrentSecond()), 1000 ); this.setState({ intervalFunc: intervalFunc }); const down = (time) => { if (time > 0) { // converts seconds to MM:SS at every t-minus this.setState({ timeLeft: secondsToMins(time) }); /* console.log(time); console.log(this.state.timeLeft);*/ } let sound = document.getElementById(id).childNodes[0]; if (time <= 0) { sound.play(); this.setState({ timeLeft: secondsToMins(time) }); console.log(`##########`); console.log(time); // console.log(this.stateIndex); console.log(this.state.init); console.log(this.state.timeLeftSeconds); console.log(`##########`); // let stateIndex = (this.state.stateIndex + 1) % states.length; // this.setState({ stateIndex: stateIndex }); this.setState({ init: this.state.init === "session" ? "break" : "session" }); this.setState({ timeLeftSeconds: this.state.init === "session" ? this.state.sessionLength * 60 + 1 : this.state.breakLength * 60 + 1 }); console.log(`##########`); console.log(time); // console.log(this.stateIndex); console.log(this.state.init); console.log(this.state.timeLeftSeconds); console.log(`##########`); } }; // down(this.decreaseCurrentSecond()); } render() { return ( <div id="clock"> <h1 id="title">25-5 Clock</h1> <div> <p id="break-label">Break Length</p> <p id="break-length">{this.state.breakLength}</p> <button id="break-decrement" onClick={(e) => this.breakDecrement()}> {" "} Decrease{" "} </button> <button id="break-increment" onClick={(e) => this.breakIncrement()}> {" "} Increase{" "} </button> </div> <div> <p id="session-label">Session Length</p> <p id="session-length">{this.state.sessionLength}</p> <button id="session-decrement" onClick={(e) => this.sessionDecrement()} > {" "} Decrease{" "} </button> <button id="session-increment" onClick={(e) => this.sessionIncrement()} > {" "} Increase{" "} </button> </div> <hr /> <div> <p id="timer-label">{this.state.init}</p> <p id="time-left">{this.state.timeLeft}</p> <button id="start_stop" onClick={(e) => this.startStop(e.target.id)}> <audio id="beep" src="./beep.mp3"></audio> start/stop{" "} </button> <button id="reset" onClick={(e) => this.reset()}> {" "} reset{" "} </button> </div> </div> ); }}/* * Render the above component into the div#app */ReactDOM.render(<Clock />, document.getElementById("app"));https://codesandbox.io/s/heuristic-star-i3t8m?file=/src/index.js