React, ES6 - getInitialState düz bir JavaScript sınıfında tanımlandı


115

Aşağıdaki bileşene sahibim ( radioOther.jsx):

 'use strict';

 //module.exports = <-- omitted in update

   class RadioOther extends React.Component {

     // omitted in update 
     // getInitialState() {
     //    propTypes: {
     //        name: React.PropTypes.string.isRequired
     //    }
     //    return {
     //       otherChecked: false
     //   }
     // }

     componentDidUpdate(prevProps, prevState) {
         var otherRadBtn = this.refs.otherRadBtn.getDOMNode();

         if (prevState.otherChecked !== otherRadBtn.checked) {
             console.log('Other radio btn clicked.')
             this.setState({
                 otherChecked: otherRadBtn.checked,
             });
         }
     }

     onRadChange(e) {
         var input = e.target;
         this.setState({
             otherChecked: input.checked
         });
     }

     render() {
         return (
             <div>
                 <p className="form-group radio">
                     <label>
                         <input type="radio"
                                ref="otherRadBtn"
                                onChange={this.onRadChange}
                                name={this.props.name}
                                value="other"/>
                         Other
                     </label>
                     {this.state.otherChecked ?
                         (<label className="form-inline">
                             Please Specify:
                             <input
                                 placeholder="Please Specify"
                                 type="text"
                                 name="referrer_other"
                                 />
                         </label>)
                         :
                         ('')
                     }
                 </p>
             </div>
         )
     }
 };

ECMAScript6'yı kullanmadan önce her şey yolundaydı, şimdi 1 hata, 1 uyarı alıyorum ve bir takip sorum var:

Hata: Yakalanmamış TypeError: null 'otherChecked' özelliği okunamıyor

Uyarı: getInitialState, düz bir JavaScript sınıfı olan RadioOther üzerinde tanımlandı. Bu yalnızca React.createClass kullanılarak oluşturulan sınıflar için desteklenir. Bunun yerine bir devlet mülkü tanımlamak mı istediniz?


  1. Hatanın nerede olduğunu görebilen var mı, bunun DOM'daki koşullu ifadeden kaynaklandığını biliyorum, ancak görünüşe göre başlangıç ​​değerini doğru olarak beyan etmiyorum?

  2. GetInitialState'i statik yapmalı mıyım

  3. GetInitialState doğru değilse mülk türlerimi bildirmek için uygun yer neresidir?

GÜNCELLEME:

   RadioOther.propTypes = {
       name: React.PropTypes.string,
       other: React.PropTypes.bool,
       options: React.PropTypes.array }

   module.exports = RadioOther;

@ssorallen, bu kod:

     constructor(props) {
         this.state = {
             otherChecked: false,
         };
     }

üretir "Uncaught ReferenceError: this is not defined"ve aşağıda bunu düzeltir

     constructor(props) {
     super(props);
         this.state = {
             otherChecked: false,
         };
     }

ancak şimdi, diğer düğmeye tıklamak artık hata veriyor:

Uncaught TypeError: Cannot read property 'props' of undefined


1
ES6 sınıfları için diğer değişiklik yöntemleri değildir sizin gibi bir işlevi geçerken anlam örneğine "otomatik bağlı" olduğunu onChange={this.onRadChange}, thisörneğin kırmızı ifade etmez onRadChangedenir. İçeri bağlama geri aramaları gerekir renderveya yapıcı bunu yapmak: onChange={this.onRadChange.bind(this)}.
Ross Allen

Yanıtlar:


239
  • getInitialStateES6 sınıflarında kullanılmaz. Bunun yerine this.stateyapıcıda atayın .
  • propTypes statik bir sınıf değişkeni olmalı veya sınıfa atanmalıdır, bileşen örneklerine atanmamalıdır.
  • Üye yöntemleri, ES6 sınıflarında "otomatik olarak bağlanmaz" . Geri çağırma olarak kullanılan yöntemler için, sınıf özelliği başlatıcılarını kullanın veya yapıcıda ilişkili örnekler atayın.
export default class RadioOther extends React.Component {

  static propTypes = {
    name: React.PropTypes.string.isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      otherChecked: false,
    };
  }

  // Class property initializer. `this` will be the instance when
  // the function is called.
  onRadChange = () => {
    ...
  };

  ...

}

React'in ES6 Sınıfları ile ilgili belgelerinde daha fazlasını görün: Bir Fonksiyonu Sınıfa Dönüştürme


Bir yıl sonra ve şimdi şunu alabilirsiniz: Uncaught TypeError: Cannot read property 'bind' of undefinedhata Herhangi bir fikir?
Jamie Hutber

@JamieHutber Kodunuzla yeni bir soru oluşturabilir misiniz? Yöntem sınıfta tanımlıysa, neden bu hatayı alacağınızı bilmiyorum.
Ross Allen

Öneriniz için teşekkürler @KennethWorden. React belgeleri için bir sorun açtım: github.com/facebook/react/issues/7746
Ross Allen

'Onları yerinde bağla' yukarıda gösterdiğiniz gibi bir ok işlevinin kullanılması anlamına mı geliyor? Elbette işe yarıyor. Oh, javascript!
jomofrodo

@jomofrodo Bu belirsiz, buna işaret ettiğiniz için teşekkürler. Demek istediğim, renderbuna benzer bir şey yapabilirsiniz onClick={this.doFoo.bind(this)}, ama kasıtlı olarak onu koda dahil etmedim çünkü bağlanmanın en az verimli yolu budur çünkü rendersık sık çağrılabilir ve her aramada yeni işlevler yaratabilir. Bu dili cevaptan çıkaracağım.
Ross Allen

4

Ekleme Ross'un cevap.

Ayrıca yeni kullanabilirsiniz ES6 ok fonksiyonu onChange mülkiyet

Yapıcıda tanımlamaya işlevsel olarak eşdeğerdir, this.onRadChange = this.onRadChange.bind(this);ancak bence daha özlüdür.

Sizin durumunuzda radyo düğmesi aşağıdaki gibi görünecektir.

<input type="radio"
       ref="otherRadBtn"
       onChange={(e)=> this.onRadChange(e)}
       name={this.props.name}
       value="other"/>

Güncelleme

Bu "daha özlü" yöntem, @Ross Allen'ın yanıtında belirtilen seçeneklerden daha az etkilidir çünkü render()yöntem her çağrıldığında yeni bir işlev oluşturur.


1
Bu çözüm işlevsel olarak doğrudur, ancak her çağrıda yeni bir İşlev oluşturur render(birçok kez çağrılabilir). Yapıcıda bir sınıf özelliği başlatıcısı veya bağlama kullanılarak, bileşenin yapımında yalnızca bir yeni bağlı İşlev oluşturulur ve sırasında yeni İşlevler oluşturulmaz render.
Ross Allen

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.