2015-04-01 12 views
24

Özelliklere göre durumlarla ilgili bir sorunla karşılaştım. Özellikler değiştiğinde durumu değiştir ve ilk olarak React - Missing işlevi mi?

senaryo Bir çocuğun bileşenine bir özellik geçer yaratan bir Bileşen ebeveyn var. Çocuk bileşeni alınan mülke göre tepki verir. Reaktif Bir bileşenin durumunu değiştirmek için "yalnızca" uygun şekilde, componentWillMount veya componentDidMount ve componentWillReceiveProps işlevlerini kullandım kadarıyla (diğerlerinin yanı sıra, bunlara odaklanalım, çünkü getInitialState bir kez çalıştırıldı) .

Sorunum/Soru

Ben ebeveynden yeni bir özellik alır ve ben devlet değiştirmek isterseniz, yalnızca işlev componentWillReceiveProps yürütülecek ve bana setstate yürütmek için izin edecektir. Render, setStatus'a izin vermez.

Durumu en baştan ve yeni bir özellik aldığında ayarlamak istersek ne olur? Bu yüzden, getInitialState veya componentWillMount/componentDidMount üzerinde ayarladım. Sonra componentWillReceiveProps kullanarak özelliklerine bağlı olarak durumu değiştirmeniz gerekir.

Durumunuz, mülkünüzün özelliklerine bağlı olduğu için hemen hemen her zaman bir sorun yaratıyor. Aptal hale gelebilir çünkü yeni mülke göre güncellemek istediğiniz durumları tekrarlamanız gerekir.

Çözümümün

Ben componentWillMount ve componentWillReceiveProps üzerinde deniyor yeni bir yöntem oluşturduk. Bir özelliğin, oluşturulmadan önce ve Bileşenin ilk kurulduğunda güncellenmesinden sonra herhangi bir yöntem bulunamadı. O zaman bu aptalca çözümü yapmaya gerek kalmayacaktı.

Her neyse, burada soru: yeni bir özellik alındığında veya değiştirildiğinde durumun güncellenmesi için daha iyi bir seçenek yok mu?

/*...*/ 
/** 
* To be called before mounted and before updating props 
* @param props 
*/ 
prepareComponentState: function (props) { 
    var usedProps = props || this.props; 

    //set data on state/template 
    var currentResponses = this.state.candidatesResponses.filter(function (elem) { 
     return elem.questionId === usedProps.currentQuestion.id; 
    }); 
    this.setState({ 
     currentResponses: currentResponses, 
     activeAnswer: null 
    }); 
}, 
componentWillMount: function() { 
    this.prepareComponentState(); 
}, 
componentWillReceiveProps: function (nextProps) { 
    this.prepareComponentState(nextProps); 
}, 
/*...*/ 

ben biraz aptal hissediyorum, bir şey kaybetmeden ediyorum galiba ... Bunu çözmek için başka bir çözüm yoktur sanırım .

Ve evet, ben zaten bunu biliyor: Bu model genellikle çok gerekli olmadığını tespit ettik https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html

cevap

20

. Genel durumda (her zaman değil), değiştirilen özelliklere göre ayar durumunun biraz bozuk bir desen olduğunu buldum; bunun yerine, yalnızca render zamanında gerekli yerel durumunu türetin.

render: function() { 
    var currentResponses = this.state.candidatesResponses.filter(function (elem) { 
    return elem.questionId === this.props.currentQuestion.id; 
    }); 

    return ...; // use currentResponses instead of this.state.currentResponses 
} 

Ancak bazı durumlarda, (örneğin belki aşırı pahalı olması hesaplanması) bu verileri önbelleğe almak mantıklı olabilir, ya da sadece sahne/set başka bir nedenden dolayı değiştirildiğinde bilmemiz gerekir. Bu durumda, temelde sorunuza yazdığınız kalıbı kullanırdım.

Eğer gerçekten yazmayı sevmiyorsan, bu yeni yöntemi miks olarak resmileştirebilirsin.Örneğin: onlar React- alamadım çünkü Tabii

var PropsSetOrChangeMixin = { 
    componentWillMount: function() { 
    this.onPropsSetOrChange(this.props); 
    }, 

    componentWillReceiveProps: function(nextProps) { 
    this.onPropsSetOrChange(nextProps); 
    } 
}; 

React.createClass({ 
    mixins: [PropsSetOrChangeMixin], 

    onPropsSetOrChange: function(props) { 
    var currentResponses = this.state.candidatesResponses.filter(function (elem) { 
     return elem.questionId === props.currentQuestion.id; 
    }); 

    this.setState({ 
     currentResponses: currentResponses, 
     activeAnswer: null 
    }); 
    }, 

    // ... 
}); 

, Bileşenleri tepki merkezli class kullanıyorsanız, siz (örn devralma veya özel JS katmalar) bazı alternatif çözüm bulmak gerekiyordu Şu anda stil karışımları.

(For Ne değer çok kodun açık yöntemler kullanılarak daha net olduğunu düşünüyorum; muhtemelen bu :)

componentWillMount: function() { 
    this.prepareComponentState(this.props); 
}, 

componentWillReceiveProps: function (nextProps) { 
    this.prepareComponentState(nextProps); 
}, 

prepareComponentState: function (props) { 
    //set data on state/template 
    var currentResponses = this.state.candidatesResponses.filter(function (elem) { 
    return elem.questionId === props.currentQuestion.id; 
    }); 
    this.setState({ 
    currentResponses: currentResponses, 
    activeAnswer: null 
    }); 
}, 
gibi yazmak isterim
İlgili konular