我正在构建一个简单的计时器作为React的实践。现在,我只是专注于缩短工作时间。当用户在baseSeconds
中输入选择内容时,计时器将在该秒停止。
如果您将数字硬编码为prop而不是传递状态,则它会起作用。而且我知道根据我作为测试输出的{this.props.baseSeconds}
道具的变化。但是当我将this.state.baseSeconds
用作道具时,计时器会继续运行。
“设置”的父项:
const baseMin = [];
for (var i=0; i <= 60; i++) {
baseMin.push(i);
}
const baseSec = [];
for (var i=0; i <= 60; i++) {
baseSec.push(i);
}
const displayMinutes = baseMin.map((minute) =>
<option value={minute}>{minute}</option>
)
const displaySeconds = baseSec.map((second) =>
<option value={second}>{second}</option>
)
class Settings extends React.Component {
constructor(props) {
super();
this.state = {
baseMinutes: 0,
baseSeconds: 0,
varMinutes: 0,
varSeconds: 0
};
this.updateBaseMin = this.updateBaseMin.bind(this);
this.updateBaseSec = this.updateBaseSec.bind(this);
this.updateVarMin = this.updateVarMin.bind(this);
this.updateVarSec = this.updateVarSec.bind(this);
this.renderTimer = this.renderTimer.bind(this);
}
updateBaseMin(event) {
this.setState({ baseMinutes: event.target.value });
}
updateBaseSec(event) {
this.setState({ baseSeconds: event.target.value });
}
updateVarMin(event) {
this.setState({ varMinutes: event.target.value });
}
updateVarSec(event) {
this.setState({ varSeconds: event.target.value });
}
renderTimer(e) {
e.preventDefault();
const { baseMinutes, baseSeconds, varMinutes, varSeconds } = this.state;
return(
<Timer baseMinutes={baseMinutes} baseSeconds={baseSeconds} varMinutes={varMinutes} varSeconds={varSeconds}/>
)
}
render() {
const varMin = [];
for (var i=0; i <= this.state.baseMinutes; i++) {
varMin.push(i);
}
const displayBaseMin = varMin.map((minute) =>
<option value={minute}>{minute}</option>
)
const varSec = [];
for (var i=0; i <= this.state.baseSeconds; i++) {
varSec.push(i);
}
const displayBaseSec = varSec.map((second) =>
<option value={second}>{second}</option>
)
const { baseMinutes, baseSeconds, varMinutes, varSeconds } = this.state;
return (
<Container>
Settings
<form onSubmit={this.renderTimer}>BaseTime
<select onChange={this.updateBaseMin}>
{displayMinutes}
</select>
:
<select onChange={this.updateBaseSec}>
{displaySeconds}
</select>
VarTime +-
<select onChange={this.updateVarMin}>
{displayBaseMin}
</select>
:
<select onChange={this.updateVarSec}>
{displayBaseSec}
</select>
<input type="submit" value="Submit" />
</form>
<p>{this.state.baseMinutes}, {this.state.baseSeconds}, {this.state.varMinutes}, {this.state.varSeconds}</p>
<div>{this.renderTimer}</div>
<Timer baseMinutes={baseMinutes} baseSeconds={this.state.baseSeconds} varMinutes={varMinutes} varSeconds={varSeconds}/>
</Container >
)
}
}
export default Settings
计时器的子组件:
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = {
minutes: 0,
seconds: 0,
baseSeconds: this.props.baseSeconds
}
this.go = this.go.bind(this);
this.stop = this.stop.bind(this);
this.reset = this.reset.bind(this);
}
go = () => {
this.timer = setInterval(() => {
if ((this.state.seconds) === (this.props.baseSeconds)) {
clearInterval(this.timer);
} else {
this.setState({ seconds: this.state.seconds + 1 })
console.log(this.state.baseSeconds)
}
}, 1000)
}
stop = () => {
clearInterval(this.timer);
}
reset = () => {
this.setState({ minutes: 0, seconds: 0 })
}
render() {
return (
<div>
<button onClick={this.go}>start</button>
<button onClick={this.stop}>stop</button>
<button onClick={this.reset}>reset</button>
<p>{this.props.baseMinutes}:{this.props.baseSeconds}</p>
<p>{this.state.minutes}:{this.state.seconds}</p>
</div>
)
}
}
export default Timer
答案 0 :(得分:1)
是的,道具更改会导致默认情况下重新渲染。但在您的情况下,在子组件中,初始状态(baseSeconds
)是基于不建议使用的道具(this.props.baseSeconds
)。构造函数仅运行一次(在组件挂载时),之后不会检测到baseSeconds道具上的任何更新。您可以在渲染内部直接使用道具,而无需使用本地状态。如果必须使用道具更新本地状态,则建议的方法是使用getDerivedStateFromProps生命周期方法。