Bereaksi Kotak centang tidak mengirim onChange


136

TLDR: Gunakan defaultChecked alih-alih dicentang, bekerja jsbin .

Mencoba mengatur kotak centang sederhana yang akan mencoret teks labelnya ketika dicentang. Untuk beberapa alasan handleChange tidak dipecat ketika saya menggunakan komponen. Adakah yang bisa menjelaskan kesalahan saya?

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

Pemakaian:

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

Larutan:

Menggunakan dicentang tidak membiarkan nilai yang mendasarinya berubah (tampaknya) dan dengan demikian tidak memanggil penangan onChange. Beralih ke defaultChecked tampaknya memperbaiki ini:

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
Pertama, mengapa tidak menambahkan onChange yang lebih this.setState({checked: !this.state.checked})mudah daripada harus menyimpan nilai. Kemudian operator ternary di attrubute yang diperiksa:checked={this.state.checked ? 'checked': null}
zackify

Begitulah awalnya, tetapi sepertinya tidak pernah diperbarui. Jadi saya mulai mengelupas di sana-sini untuk men-debug apa yang tidak dipecat. Idealnya akan kembali ke bentuk paling sederhana ketika selesai :)
jdarling

Dengan asumsi mountNode Anda adalah dom dom yang sebenarnya, Anda harus menggunakannya this.refs.complete.getDOMNode().checked. lihat fiddle jsfiddle.net/d10xyqu1
trekforever

Dia hanya bisa menggunakan status alih-alih mendapatkan dom node: jsfiddle.net/d10xyqu1/1 Ini berfungsi dengan baik, Anda pasti salah ketik.
zackify

2
Abaikan komentar TLDR - defaultChecked tidak selalu jawabannya
Chris

Jawaban:


207

Untuk mendapatkan status yang dicentang dari kotak centang Anda, pathnya adalah:

this.refs.complete.state.checked

Alternatifnya adalah mendapatkannya dari acara yang diteruskan ke handleChangemetode:

event.target.checked

3
handleChange tidak pernah dipanggil, tidak masalah jika Anda mengklik kotak centang atau label, handleChange tidak dipanggil :(.
jdarling

13
Coba gunakan defaultChecked = {this.state.complete} alih-alih "dicentang" pada input Anda.
zbyte

Itu dia ... Mencari selamanya mencari dan melihat-lihat. Akan memperbarui pertanyaan dengan jawaban yang berfungsi seandainya orang lain menemukan ini juga.
jdarling

Tapi mengapa - memiliki masalah yang sama tetapi Anda seharusnya menggunakan checkeduntuk komponen yang dikontrol: /
Dominic

4
pengaturan checkedberarti keadaan dikelola di luar komponen. Ketika pengguna mengklik tidak ada yang bisa dihubungi handleChangekarena tidak ada keadaan yang diperbarui. Alih-alih, Anda perlu mendengarkan onClickdan memicu pembaruan status di sana.
zbyte

29

Lebih baik tidak menggunakan referensi dalam kasus seperti itu. Menggunakan:

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

Ada beberapa opsi:

checked vs. defaultChecked

Yang pertama akan menanggapi perubahan status dan klik. Yang terakhir akan mengabaikan perubahan status.

onClick vs. onChange

Yang pertama akan selalu memicu klik. Yang terakhir tidak akan memicu klik jika checkedatribut ada pada inputelemen.


10

Dalam skenario Anda TIDAK ingin menggunakan penangan onChange pada input DOM, Anda dapat menggunakan onClickproperti sebagai alternatif. The defaultChecked, kondisi dapat meninggalkan kondisi tetap untuk v16 IINM.

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

Saya harap ini membantu seseorang di masa depan.


10

Jika Anda memiliki handleChangefungsi yang terlihat seperti ini:

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

Anda dapat membuat onChangefungsi khusus sehingga berfungsi seperti input teks:

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

tidak handleChangepada inputseharusnya this.handleChange?
Ardhi

5

Jika seseorang mencari pengatur kejadian universal, kode berikut ini dapat digunakan lebih atau kurang (dengan asumsi bahwa properti nama diset untuk setiap input):

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

2

onChange tidak akan memanggil handleChange di ponsel saat menggunakan defaultChecked. Sebagai alternatif, Anda dapat menggunakan onClick dan onTouchEnd.

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

1

Dalam materi ui, keadaan kotak centang dapat diambil sebagai

this.refs.complete.state.switched
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.