Reagisci Casella di controllo che non invia onChange


136

TLDR: utilizzare defaultChecked anziché jsbin funzionante e controllato .

Tentativo di impostare una semplice casella di controllo che barrerà il testo dell'etichetta quando è selezionata. Per qualche motivo handleChange non viene attivato quando utilizzo il componente. Qualcuno può spiegare cosa sto facendo di sbagliato?

var CrossoutCheckbox = React.createClass({
  getInitialState: function () {
    return {
        complete: (!!this.props.complete) || false
      };
  },
  handleChange: function(){
    console.log('handleChange', this.refs.complete.checked); // Never gets logged
    this.setState({
      complete: this.refs.complete.checked
    });
  },
  render: function(){
    var labelStyle={
      'text-decoration': this.state.complete?'line-through':''
    };
    return (
      <span>
        <label style={labelStyle}>
          <input
            type="checkbox"
            checked={this.state.complete}
            ref="complete"
            onChange={this.handleChange}
          />
          {this.props.text}
        </label>
      </span>
    );
  }
});

Uso:

React.renderComponent(CrossoutCheckbox({text: "Text Text", complete: false}), mountNode);

Soluzione:

L'uso di controllato non consente il cambiamento del valore sottostante (apparentemente) e quindi non chiama il gestore onChange. Il passaggio a defaultChecked sembra risolvere questo problema:

var CrossoutCheckbox = React.createClass({
  getInitialState: function () {
    return {
        complete: (!!this.props.complete) || false
      };
  },
  handleChange: function(){
    this.setState({
      complete: !this.state.complete
    });
  },
  render: function(){
    var labelStyle={
      'text-decoration': this.state.complete?'line-through':''
    };
    return (
      <span>
        <label style={labelStyle}>
          <input
            type="checkbox"
            defaultChecked={this.state.complete}
            ref="complete"
            onChange={this.handleChange}
          />
          {this.props.text}
        </label>
      </span>
    );
  }
});

3
Prima di tutto, perché non aggiungere un onChange che sia più semplice this.setState({checked: !this.state.checked})che dover memorizzare un valore. Quindi un operatore ternario nell'attubato controllato:checked={this.state.checked ? 'checked': null}
zackify il

È così che è iniziato, ma non è mai sembrato aggiornarsi. Così ho iniziato a fluffare qua e là per eseguire il debug di ciò che non veniva licenziato. Idealmente tornerà alla forma più semplice una volta completato :)
jdarling

Supponendo che mountNode sia un vero nodo dom, dovresti usarlo this.refs.complete.getDOMNode().checked. vedi violino jsfiddle.net/d10xyqu1
trekforever,

Può solo usare state invece di ottenere il nodo dom però: jsfiddle.net/d10xyqu1/1 Funziona bene, devi aver sbagliato a digitare qualcosa.
Zackify,

2
Ignora il commento TLDR - defaultChecked non è sempre la risposta
Chris

Risposte:


207

Per ottenere lo stato selezionato della casella di controllo, il percorso sarebbe:

this.refs.complete.state.checked

L'alternativa è ottenerlo dall'evento passato nel handleChangemetodo:

event.target.checked

3
handleChange non viene mai chiamato, non importa se si fa clic sulla casella o sull'etichetta, handleChange non viene chiamato :(.
jdarling

13
Prova a utilizzare defaultChecked = {this.state.complete} anziché "controllato" sul tuo input.
zbyte,

Questo è tutto ... cercato per sempre guardando e frugando in giro. Aggiornerà la domanda con una risposta operativa completa nel caso in cui anche altri lo incontrino.
jdarling

Ma perché - avere lo stesso problema ma dovresti usarlo checkedper componenti controllati: /
Dominic

4
impostazione checkedsignifica che lo stato è gestito al di fuori del componente. Quando l'utente fa clic, non c'è nulla da chiamare handleChangepoiché nessuno stato viene aggiornato. Invece dovresti ascoltare onClicke attivare un aggiornamento di stato lì.
Zbyte,

29

In questi casi è meglio non usare i riferimenti. Uso:

<input
    type="checkbox"
    checked={this.state.active}
    onClick={this.handleClick}
/>

Ci sono alcune opzioni:

checked vs defaultChecked

Il primo rispondeva sia ai cambiamenti di stato che ai clic. Quest'ultimo ignorerebbe i cambiamenti di stato.

onClick vs onChange

Il primo si attiverà sempre sui clic. Quest'ultimo non si attiverebbe ai clic se l' checkedattributo è presente inputsull'elemento.


10

Nello scenario NON si desidera utilizzare il gestore onChange sul DOM di input, è possibile utilizzare la onClickproprietà in alternativa. La defaultCheckedcondizione può lasciare uno stato fisso per I16M v16.

 class CrossOutCheckbox extends Component {
      constructor(init){
          super(init);
          this.handleChange = this.handleChange.bind(this);
      }
      handleChange({target}){
          if (target.checked){
             target.removeAttribute('checked');
             target.parentNode.style.textDecoration = "";
          } else {
             target.setAttribute('checked', true);
             target.parentNode.style.textDecoration = "line-through";
          }
      }
      render(){
         return (
            <span>
              <label style={{textDecoration: this.props.complete?"line-through":""}}>
                 <input type="checkbox"
                        onClick={this.handleChange}
                        defaultChecked={this.props.complete}
                  />
              </label>
                {this.props.text}
            </span>
        )
    }
 }

Spero che questo aiuti qualcuno in futuro.


10

Se hai una handleChangefunzione simile a questa:

handleChange = (e) => {
  this.setState({
    [e.target.name]: e.target.value,
  });
}

È possibile creare una onChangefunzione personalizzata in modo che si comporti come un input di testo:

<input
  type="checkbox"
  name="check"
  checked={this.state.check}
  onChange={(e) => {
    this.handleChange({
      target: {
        name: e.target.name,
        value: e.target.checked,
      },
    });
  }}
/>

non è handleChangeacceso inputdovrebbe essere this.handleChange?
Ardhi,

5

Nel caso in cui qualcuno stia cercando un gestore di eventi universale, è possibile utilizzare più o meno il seguente codice (supponendo che la proprietà name sia impostata per ogni input):

    this.handleInputChange = (e) => {
        item[e.target.name] = e.target.type === "checkbox" ? e.target.checked : e.target.value;
    }

2

onChange non chiamerà handleChange su dispositivo mobile quando si utilizza defaultChecked. In alternativa puoi usare onClick e onTouchEnd.

<input onClick={this.handleChange} onTouchEnd={this.handleChange} type="checkbox" defaultChecked={!!this.state.complete} />;

1

Nell'interfaccia utente materiale, lo stato della casella di controllo può essere recuperato come

this.refs.complete.state.switched
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.