ReactJS: setTimeout () çalışmıyor mu?


104

Bu kodu akılda tutarak:

var Component = React.createClass({

    getInitialState: function () {
        return {position: 0};    
    },

    componentDidMount: function () {
        setTimeout(this.setState({position: 1}), 3000);
    },

    render: function () {
         return (
            <div className="component">
                {this.state.position}
            </div>
         ); 
    }

});

ReactDOM.render(
    <Component />,
    document.getElementById('main')
);

Durumun ancak 3 saniye sonra değişmesi gerekmiyor mu? Hemen değişiyor.

Buradaki asıl amacım durumu her 3 saniyede bir (ile setInterval()) değiştirmektir, ancak çalışmadığı için denedim setTimeout(), bu da çalışmıyor. Bunun üzerinde ışık var mı? Teşekkürler!


2
Eğer varsa foo(bar())o zaman barolduğu ilk idam ve döndürdüğü değer geçirilir foo.
Felix Kling

@FelixKling doğru görünüyor, ancak uygun değil. Yana foo()burada tam olarak çalıştırmak için baristenen zaman aşımı sonra. Ya da tamamen yanılıyor muyum ve bu hemen işliyor ve yalnızca istenen süreden sonra değeri döndürüyor mu?
jbarradas

3
"Buradaki foo (), istenen zaman aşımından sonra tam olarak çubuğu yürütmek olduğundan." Doğru, bu yüzden geçmek zorundasın bar, çağırıp geri dönüş değerini iletmek değil. foo(bar())Ne fooyaptığına bağlı olarak davranışının değişmesini mi bekliyordun ? Bu gerçekten tuhaf olurdu.
Felix Kling

Yanıtlar:


246

Yapmak

setTimeout(
    function() {
        this.setState({ position: 1 });
    }
    .bind(this),
    3000
);

Aksi takdirde, sonucunu geçiyoruz setStateiçin setTimeout.

thisAnahtar kelime kullanımını önlemek için ES6 ok işlevlerini de kullanabilirsiniz :

setTimeout(
  () => this.setState({ position: 1 }), 
  3000
);

1
Evet mantıklı ve işe yarıyor. Ancak function () bir işlev değil mi? Öyleyse neden bağlamamız gerekiyor? Zaten denedim ve gerçekten gerekli, sadece nedenini bilmek istedim.
Yardımınız

Neden sonucun setTimeout'a geçeceğini söylediğinizi anlamıyorum, bu nasıl işe yaramaz? Bu durumda davranış nedir?
PositiveGuy

16
: kullanmayı tercih olanlarınız için ES6 işlevlerini ok setTimeout(() => {this.setState({ position: 1 })}, 3000)kendi başınıza bu araştırdık eğer @PositiveGuy emin bu soru yayınlanmıştır değil çünkü, ama durumda değil var: Daniel'in orijinal örnek ihtiyaçlarını .bind(this)kısıtlamak için thisbağlam setState- Aksi , thisotomatik olarak çağrıldığı bağlama başvurur (bu durumda, anonim functiongeçilir setTimeout). Bununla birlikte, ES6 ok işlevleri sözcüksel olarak kapsamlıdır - thisçağrıldıkları bağlamla sınırlıdırlar .
Zac Collier

1
Çalışmıyor ... setTimeout (() => {if (! This.props.logoIsLoading &&! This.props.isLoading) {console.log ('Olacak mıyız?'); This.setState ({.. .this.state, shouldUpdate: false, itemToUpdate: null, modalIsOpen: false, modalTitle: 'Yeni Organizasyon Ekle'});}}, 100); Sınıf sözdizimsel şeker sınıfı bağlamında Kuruluşlar Bileşeni genişletir {console.log hiçbir zaman console.log almaz ('Olacak mıyız?'); Ondan önceki ve sonraki her şey günlüğe kaydedilir.
juslintek

@juslintek çalışmamayı tanımlar. lütfen gerekirse yeni bir soru sorun.
Daniel A. White

151
setTimeout(() => {
  this.setState({ position: 1 });
}, 3000);

Yukarıdakiler de işe yarar çünkü ES6 ok işlevi bağlamını değiştirmez this.


3
ES6 sözdizimi, React'teki en iyi uygulamalar için kabul edilen yanıt olmalıdır. Her ikisi de işe yarayacak, ancak bu daha zarif ve kulplu this.
mccambridge

24

Herhangi bir zaman aşımı oluşturduğumuzda, henüz ateşlenmediyse, componentWillUnmount'ta onu temizlemeliyiz.

      let myVar;
         const Component = React.createClass({

            getInitialState: function () {
                return {position: 0};    
            },

            componentDidMount: function () {
                 myVar = setTimeout(()=> this.setState({position: 1}), 3000)
            },

            componentWillUnmount: () => {
              clearTimeout(myVar);
             };
            render: function () {
                 return (
                    <div className="component">
                        {this.state.position}
                    </div>
                 ); 
            }

        });

ReactDOM.render(
    <Component />,
    document.getElementById('main')
);

12

Bunun biraz eski olduğunu biliyorum, ancak React'in bileşen ayrıldığında aralığı temizlemeyi önerdiğini fark etmek önemlidir: https://reactjs.org/docs/state-and-lifecycle.html

Bu yüzden bu yanıtı bu tartışmaya eklemeyi seviyorum:

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
  componentWillUnmount() {
    clearInterval(this.timerID);
  }

8

setStateparantez nedeniyle hemen çağrılıyor! Anonim bir işleve sarın, sonra adlandırın:

setTimeout(function() {
    this.setState({position: 1})
}.bind(this), 3000);

6

SetTimeout'u kimin aradığını söylemedin

Burada ek işlevleri çağırmadan zaman aşımını nasıl çağıracağınız.

1. Bunu ek işlevler yapmadan yapabilirsiniz.

setTimeout(this.setState.bind(this, {position:1}), 3000);

Function.prototype.bind () kullanır

setTimeout, işlevin yerini alır ve bağlam içinde tutar.

2. Daha az kod yazarak bile aynısını yapmanın başka bir yolu.

setTimeout(this.setState, 3000, {position:1});

Muhtemelen bir noktada aynı bağlama yöntemini kullanıyor

SetTimeout yalnızca işlevin konumunu alır ve işlev zaten içeriğe sahiptir? Neyse, işe yarıyor!

NOT: Bunlar js'de kullandığınız herhangi bir işlevle çalışır.


5

Kod kapsamınız ( this) , windowtepki bileşeniniz değil, nesneniz olacaktır ve bu yüzdensetTimeout(this.setState({position: 1}), 3000) bu şekilde çökecektir.

Bu javascript'ten geliyor, React değil, js closeure


Dolayısıyla, mevcut react bileşen kapsamınızı bağlamak için şunu yapın:

setTimeout(function(){this.setState({position: 1})}.bind(this), 3000);

Veya tarayıcınız es6'yı destekliyorsa veya projeleriniz es6'dan es5'e derleme desteğine sahipse, arrow func 'bu' sorunu düzeltmek için ok işlevini de deneyin:

setTimeout(()=>this.setState({position: 1}), 3000);

3

'SetTimeout' işlevinin içindeki kapsama erişmenin 3 yolu vardır

İlk,

const self = this
setTimeout(function() {
  self.setState({position:1})
}, 3000)

İkincisi, ES6 ok işlevini kullanmaktır, çünkü ok işlevinin kendi kapsamı yoktu (bu)

setTimeout(()=> {
   this.setState({position:1})
}, 3000)

Üçüncüsü, kapsamı işlevin içine bağlamaktır

setTimeout(function(){
   this.setState({position:1})
}.bind(this), 3000)

1

Sözdizimi bildirim hatası yaptınız, uygun setTimeout bildirimini kullanın

message:() => { 
  setTimeout(() => {this.setState({opened:false})},3000); 
  return 'Thanks for your time, have a nice day 😊! 
}

0

Ayarlanan zaman aşımının ES6 sözdizimini kullanmayı deneyin. Normal javascript setTimeout () react js'de çalışmaz

setTimeout(
      () => this.setState({ position: 100 }), 
      5000
    );
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.