2017-03-04 54 views
9

Tamam, bunu hızlı bir şekilde yapmaya çalışacağım çünkü kolay bir düzeltme olmalı ...Neden setState yöntemini çağırmak durumu hemen değiştirmiyor?

Bir sürü benzer soru okudum ve cevap oldukça açık görünüyor. İlk etapta bakmak zorunda kalacağım hiçbir şey yok! Ama ... nasıl düzeltileceğini ya da neden olduğunu anlayamayacağım bir hata yaşıyorum.

olarak aşağıdaki gibidir:

class NightlifeTypes extends Component { 
constructor(props) { 
    super(props); 

    this.state = { 
     barClubLounge: false, 
     seeTheTown: true, 
     eventsEntertainment: true, 
     familyFriendlyOnly: false 
    } 
    this.handleOnChange = this.handleOnChange.bind(this); 
} 

handleOnChange = (event) => { 
    if(event.target.className == "barClubLounge") { 
     this.setState({barClubLounge: event.target.checked}); 
     console.log(event.target.checked) 
     console.log(this.state.barClubLounge) 
    } 
} 

render() { 
    return (
     <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/> 
    ) 
} 

Daha kod bu çevreler ancak sorun burada yatıyor budur. Çalışmalı mıyım?

Ben de bu denedim:

handleOnChange = (event) => { 
if(event.target.className == "barClubLounge") { 
    this.setState({barClubLounge: !this.state.barClubLounge}); 
    console.log(event.target.checked) 
    console.log(this.state.barClubLounge) 
} 

Yani bu iki console.log() 's var, ikisi de aynı olmalıdır. Tam anlamıyla devleti, yukarıdaki satırdaki event.target.checked ile aynı olacak şekilde ayarlıyorum!

Fakat her zaman gerekenin tersini verir.

!this.state.barClubLounge; Eğer false başlarsa, ilk tıklamamda onay kutusu işaretli olup olmamasına rağmen, durumun kapalı olmasına rağmen yanlış kalır!

Bu çılgın bir paradoks ve ben ne oluyor, lütfen yardım fikrim yok!

cevap

19

Nedeni değerin bir callback yöntemi kullanmak kontrol etmek istiyorsanız, sadece setState sonra güncellenir state değerini bekleyemezsiniz, setState asenkron olmasıdır. setState görevini tamamladıktan sonra çalıştırılacak bir geri çağırma yöntemi olarak geçirin.

Neden setState asenkron nedir?

Bunun nedeni, setState'un state değerini değiştirmesi ve yeniden oluşturulmasına neden olmasıdır. Bu pahalı bir işlem olabilir ve synchronous tarayıcının yanıt vermemesine neden olabilir. Böylece setState aramalar asynchronous yanı sıra daha iyi bir arayüz deneyimi ve performans için harmanlanmıştır vardır.

Doc kaynaktan:

setState() hemen this.state mutasyona ancak bekleyen durum geçişini yaratır. Bu yöntemini çağırdıktan sonra this.state öğesine erişme, varolan değeri potansiyel olarak iade edebilir. setstate ve çağrılar performans kazançları için batched edilebilir aramaların senkron çalışma hiçbir garantisi yoktur.setstate ile

kullanma geri arama yöntemi:

, sadece setState sonra güncellenir state değerini kontrol böyle bir geri arama yöntemi kullanmak için:

setState({ key: value },() => { 
    console.log('updated state value', this.state.key) 
}) 

kontrol bu:

class NightlifeTypes extends React.Component { 
 
    constructor(props) { 
 
     super(props); 
 

 
     this.state = { 
 
     barClubLounge: false, 
 
     seeTheTown: true, 
 
     eventsEntertainment: true, 
 
     familyFriendlyOnly: false 
 
     } 
 
     this.handleOnChange = this.handleOnChange.bind(this); 
 
    } 
 

 
    handleOnChange = (event) => { 
 
     let value = event.target.checked; 
 

 
     if(event.target.className == "barClubLounge") { 
 

 
     this.setState({ barClubLounge: value},() => { //here 
 
      console.log(value); 
 
      console.log(this.state.barClubLounge); 
 
      //both will print same value 
 
     });   
 

 
     } 
 
    } 
 

 
    render() { 
 
     return (
 
      <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/> 
 
    ) 
 
    } 
 
} 
 

 
ReactDOM.render(<NightlifeTypes/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 

 
<div id='app'/>

0

Bu, performans değerlendirmeleri nedeniyle tasarım gereğidir. Tepki olarak setstate pahalı bir CPU işlem olup bileşeni, yeniden oluşturmak garanti fonksiyonu olup. Bunun gibi, onun tasarımcılar dolayısıyla setState eşzamansızsa, içine birden fazla render işlemleri toplayarak optimize etmek istedi.