2015-10-03 15 views
17

Quando faccio clic sulla casella di controllo, il segno di spunta non scompare sebbene il console.log nel gestore onChange indichi lo stato modificato in falso. D'altra parte, quando lo stato viene modificato da un pulsante separato, il segno di spunta si attiva e disattiva correttamente.La casella di controllo React non si attiva

export default class TestComponent extends Component { 

constructor(props) { 
    super(props); 
    this.state = { 
     is_checked: true 
    }; 
    this.updateCheckbox = this.updateCheckbox.bind(this); 
    this.pressButton = this.pressButton.bind(this); 
} 
updateCheckbox(event) { 
    event.preventDefault(); 

    this.setState({is_checked: !this.state.is_checked}); 
    console.log(this.state.is_checked); // This logs 'false' meaning the click did cause the state change 
    console.log(event.target.checked); // However, this logs 'true' because the checkmark is still there 

} 
pressButton(event){ 
    event.preventDefault(); 
    this.setState({is_checked: !this.state.is_checked}); 
} 
render(){ 

    return (
    <input type="checkbox" onChange={this.updateCheckbox} checked={this.state.is_checked} ></input> 
    <button onClick={this.pressButton}>change checkbox state using button</button> 
    ); 
} 
} 
+0

So che è stato un po ', ma la risposta accettata è in qualche modo fuorviante (non male però). Inoltre, penso che non dovresti risolvere questo problema con l'associazione a due vie, come hai fatto nella tua risposta. – ftor

risposta

20

Penso di vedere cosa sta succedendo.

Si fa clic sul pulsante e si attiva is_checked, che verifica o deseleziona la casella. Ma questo finisce per attivare un onChange per la casella di controllo, che alterna anche lo stato ... In realtà hai codificato un ciclo infinito. Sebbene, dal momento che React esegue il batch/debouncing delle operazioni setState, il tuo codice non bloccherà la pagina.

Prova questo:

var React = require("react"); 

var Component = React.createClass({ 
    getInitialState: function() { 
     return { 
      isChecked: true 
     }; 
    }, 

    handleCheckboxChange: function(event) { 
     console.log("checkbox changed!", event); 
     this.setState({isChecked: event.target.checked}); 
    }, 

    toggleIsChecked: function() { 
     console.log("toggling isChecked value!"); 
     this.setState({isChecked: !this.state.isChecked}); 
    }, 

    handleButtonClick: function(event) { 
     console.log("button was pressed!", event); 
     this.toggleIsChecked(); 
    }, 

    render: function() { 
     return (
      <div> 
       <input type="checkbox" onChange={this.handleCheckboxChange} checked={this.state.isChecked} /> 
       <button onClick={this.handleButtonClick}>change checkbox state using this button</button> 
      </div> 
     ); 
    } 
}); 

module.exports = Component; 

Nota che si può fare questo codice ancora più pulito utilizzando di React Valuelink (maggiori informazioni qui: https://facebook.github.io/react/docs/two-way-binding-helpers.html)

+0

Grazie per il vostro aiuto. Il codice che hai fornito ha lo stesso problema, ma il link per il collegamento bidirezionale è stato utile. Aggiornato il mio post per mostrare la soluzione di lavoro. –

+0

Ho dimenticato di aggiungere la riga all'interno di "handleCheckboxChange' dove effettivamente aggiorna lo stato" isChecked "- il segreto sta usando il valore di" event.target.checked ". Ho aggiornato il codice, solo per riferimento. Anche questo è un gioco da ragazzi: https://jsfiddle.net/xqb2mxsq/ – sarink

+1

Puoi anche risolvere questo problema semplicemente rimuovendo "event.preventDefault();" linea. Dal momento che impedisce il checkbox da controllare. quindi sarà sempre lo stesso stato. –

0

Modificato il codice per la documentazione Reagire sul legame a due vie che Kabir ha fornito il link per.

per farlo funzionare ho dovuto

  1. uso "React.createClass" invece di "si estende Componente" al fine di utilizzare il LinkedStateMixin

    import react from 'react/addons' 
    
    var TestComponent = React.createClass({ 
    mixins: [React.addons.LinkedStateMixin], 
    render: function(){ .... 
    
  2. remove onChange = 'updateCheckbox' e usa invece this.linkState.

    <input type="checkbox" checkedLink={this.linkState(this.state.is_checked)} ></input> 
    
7

La ragione di questo comportamento ha a che fare con un dettaglio di implementazione di React - più in particolare il modo in cui Reagire normalizza modificare la gestione del cross browser. Con gli ingressi radio e casella di controllo React utilizza un evento click al posto di un evento change. Quando si applica preventDefault all'interno di un gestore eventi collegato, ciò impedisce al browser di aggiornare visivamente l'input della radio/casella di controllo. Ci sono due soluzioni possibili:

  • uso stopPropagation alternativamente
  • mettere la levetta in setTimeout: setTimeout(x => this.setState(x), 0, {is_checked: !this.state.is_checked});

Preferibilmente non si utilizza preventDefault affatto, a meno che non sia assolutamente necessario.

Consultare questo React Github issue per ulteriori informazioni.

+1

eliminazione di preventDefualt risolto il problema per me, utilizzando react 15 e typescript 2.2 (mi dispiace per la formattazione errata) toggleMyCheckbox (checkboxExent: React.ChangeEvent ) { checkboxExent.preventDefault(); this.setState ({ checkboxModel: this.state.checkboxModel, controllato: this.state.checked }) } a .. toggleMyCheckbox (checkboxExent: React.ChangeEvent ) { questo. setState ({ checkboxModel: this.state.checkboxModel, controllato: this.state.checked }) } –

+0

Thank You mi sono liberato di default prevenire anche, e ha funzionato per me. –

0

Tenete a mente che setState è asincrona, quindi:

console.log(event.target.checked); 

non si riflettono immediatamente le modifiche.Il mio modo di gestire diversi campi casella di controllo:

toggleCheckbox(name, event) { 
    let obj = {}; 
    obj[name] = !this.state[name]; 
    this.setState(obj); 
} 

I campi:

<input type="checkbox" name="active" value={this.state.active} checked={this.state.active} onChange={this.toggleCheckbox.bind(this, 'active')} /> 

<input type="checkbox" name="qtype" value={this.state.qtype} checked={this.state.qtype} onChange={this.toggleCheckbox.bind(this, 'qtype')} /> 
Problemi correlati