ClearInterval'ım setInterval'ı neden durduramıyor?
React'te tamamen yeniyim. Uygulamaya çalıştığım şey bir zamanlayıcı. Saat, dakika veya saniyeye tıklandığında zamanlayıcı durur ve seçilen için, giriş düğmesi tıklandığında bir giriş alanına dönüşür, daha fazla giriş alanı göstermemeli ve saati geri başlatmalıdır. nasıl görünüyor
Flexbox konteynerine tıkladığımda alt bileşene yeni sahne aktarmayı durdurmaya çalışıyorum. Durumdaki güncelleme değişkenine bir handleClick işlevi ve setInterval () veya clearInterval () tabanı yazdım.
İstediğim, saat / dakika / saniyeden herhangi birine tıkladığımda, dosyalanan seçim dosyalanan girdiye dönüşecek ve zamanlayıcı duracak. Enter'a bastığımda zamanlayıcıya geri dönecek.
class Timer extends React.Component{
constructor(props){
super (props);
this.timerRef = React.createRef();
this.state = {
hh: new Date().getHours().toString().padStart(2,"0"),
mm: new Date().getMinutes().toString().padStart(2,"0"),
ss: new Date().getSeconds().toString().padStart(2,"0"),
suffix: new Date().getHours() > 12 ? "PM" : "AM",
update:true,
};
}
tick() {
this.setState({
hh: new Date().getHours().toString().padStart(2,"0"),
mm: new Date().getMinutes().toString().padStart(2,"0"),
ss: new Date().getSeconds().toString().padStart(2,"0"),
suffix: new Date().getHours() > 12 ? "PM" : "AM",
})
}
componentDidMount(){
this.intervalId = setInterval(
() => this.tick(), 1000
);
}
componentWillUnmount(){
clearInterval(this.intervalId);
}
handleClick(){
this.setState(state => ({update: !state.update}));
console.log("1",this.state.update);
if (this.state.update){
this.intervalId = setInterval(
() => this.tick(), 1000
);
console.log("2 set interval",this.intervalId);
}
else{
clearInterval(this.intervalId);
console.log("2 clear interval");
}
}
render() {
const { hh, mm, ss, suffix } = this.state;
return (
<div className="box" > London Clock
<div className="flexbox-container" onClick={() => this.handleClick()}>
<Content time={hh}></Content>
<div><p>:</p></div>
<Content time={mm}></Content>
<div><p>:</p></div>
<Content time={ss}></Content>
<div className="suffix"><p>{suffix}</p></div>
</div>
</div>
);
}
}
class Content extends React.Component {
state = {
editMode: false,
time: ""
};
componentDidMount(){
this.setState({
time: this.props.time,
})
}
handleKeyDown(event){
console.log(event,event.key === 'Enter');
if (event.key === 'Enter'){
this.setState({
editMode: false,
})
}
}
render() {
const {editMode} = this.state;
return (
<div>
{editMode? (
<p>
<input
defaultValue={this.props.time}
onKeyPress={e => this.handleKeyDown(e)}
/>
</p>
) : (
<p onClick={() => this.setState({ editMode: true })}>{this.props.time}</p>
)}
</div>
);
}
}
ReactDOM.render(
<Timer/>,
document.body
);
.flexbox-container {
display: flex;
flex-direction: row;
}
.suffix{
padding-left: 20px;
}
.box{
border-style: solid;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Yanıtlar
Bileşeniniz monte edildiğinde, bir aralık başlatacak ve ona atayacaktır intervalId.
Tıklama işleyiciniz durumu değiştirir ve ardından güncellenmesini beklemeden duruma bakmaya çalışır. Durum muhtemelen bu noktada güncellenmez, bu nedenle aralığı yeniden atayarak bir zombi güncelleyici ile sonuçlanır.
setState(updater, [callback])Aralık mantığınızı bir geri aramayı iletin veya aralık mantığınızı taşıyın componentDidUpdate; bu, aralık mantığının yinelemesini kaldırmanıza olanak tanır.
tickİşlevinizi belirtmek ve bağlamak için ayarlamak yerine aşağıdaki gibi deneyin .
componentDidMount(){
this.intervalId = setInterval(
() => this.tick.bind(this), 1000
);
}
componentWillUnmount(){
clearInterval(this.intervalId);
}
Devlet yerine React's Ref'i kullanabileceğinizi düşünüyorum.
constructor(props) {
this.timerRef = React.createRef();
}
componentDidMount() {
this.timerRef.current = setInterval(this.tick, 1000);
}
componentWillUnmount() {
clearInterval(this.timerRef.current);
}