2015-06-08 8 views
109

Ho il seguente componente (radioOther.jsx):Reagire, ES6 - getInitialState è stato definito su una pianura JavaScript classe

'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> 
     ) 
    } 
}; 

Prima di utilizzare ECMAScript6 tutto andava bene, ora sto ottenendo 1 errore, 1 avvertimento e io avere una domanda followup:

Error: Uncaught TypeError: Cannot read property 'otherChecked' of null

Warning: getInitialState was defined on RadioOther, a plain JavaScript class. This is only supported for classes created using React.createClass. Did you mean to define a state property instead?


  1. chiunque può vedere dove le bugie di errore, lo so che è dovuto l'istruzione condizionale nel DOM ma apparentemente non sto dichiarando correttamente il suo valore iniziale?

  2. Devo fare getInitialState statico

  3. Dove è il luogo adatto per dichiarare i miei proptypes se getInitialState non è corretta?

UPDATE:

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

    module.exports = RadioOther; 

@ssorallen, questo codice:

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

produce "Uncaught ReferenceError: this is not defined", e mentre sotto corregge che

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

ma ora, cliccando l'altro pulsante ora produce errore:

Uncaught TypeError: Cannot read property 'props' of undefined

+1

L'altra modifica per le classi ES6 è che i metodi non sono "auto-associati" all'istanza, cioè quando si passa una funzione come "onChange = {this.onRadChange}", "this" non si riferisce all'istanza quando "onRadChange 'è chiamato. È necessario associare i callback in 'render' o farlo nel costruttore:' onChange = {this.onRadChange.bind (this)} '. –

risposta

230
  • getInitialState non viene utilizzato nelle classi ES6. Assegnare invece this.state nel costruttore.
  • propTypes deve essere una variabile di classe statica o assegnata alla classe, non deve essere assegnata alle istanze del componente.
  • I metodi membri non sono "auto-bound" nelle classi ES6. Per i metodi utilizzati come callback, utilizzare class property initializers o assegnare istanze associate nel costruttore.
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 =() => { 
    ... 
    }; 

    ... 

} 

Visualizza maggiori nella documentazione del React su Classes ES6: https://reactjs.org/docs/state-and-lifecycle.html#converting-a-function-to-a-class

+0

Un anno e ora potresti scoprire: 'Uncaught TypeError: Impossibile leggere l'errore 'bind' della proprietà 'nessuna idea? –

+0

@JamieHutber Puoi creare una nuova domanda con il tuo codice? Se il metodo è definito sulla classe, non so perché si otterrebbe quell'errore. –

+0

Grazie per il suggerimento, @KennethWorden. Ho aperto un problema per i documenti di React: https://github.com/facebook/react/issues/7746 –

4

Aggiungendo a Ross's risposta.

Si potrebbe anche usare la nuova ES6 arrow function sulla proprietà onChange

E 'funzionalmente equivalente alla definizione this.onRadChange = this.onRadChange.bind(this); nel costruttore, ma è più conciso, a mio parere.

Nel tuo caso il pulsante di opzione avrà il seguente aspetto.

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

Aggiornamento

Questo metodo "più conciso" è meno efficiente rispetto alle opzioni di cui la risposta di @Ross Allen perché genera una nuova funzione ogni volta che il metodo render() viene chiamato

+1

Questa soluzione è funzionalmente corretta, ma crea una nuova funzione per ogni chiamata a 'render' (che potrebbe essere chiamata più volte). Utilizzando un inizializzatore di proprietà di classe o l'associazione nel costruttore, solo una nuova funzione associata viene creata per la costruzione del componente e non vengono create nuove funzioni durante il rendering. –

1

Se si utilizza babel-plugin-transform-class-properties o babel-preset-stage-2 (o stage-1 o stage-0), è possibile utilizzare questa sintassi:

class RadioOther extends React.Component { 

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

    state = { 
     otherChecked: false, 
    }; 

    onRadChange =() => { 
    ... 
    }; 

    ... 

} 
Problemi correlati