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>
    );
  }
});
jarling
sumber
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
zbyte
sumber
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.

Lin
sumber
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.

akiespenc
sumber
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,
      },
    });
  }}
/>
spencer.sm
sumber
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;
    }
Pawel Gorczynski
sumber
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} />;
tanner burton
sumber
1

Dalam materi ui, keadaan kotak centang dapat diambil sebagai

this.refs.complete.state.switched
Sakshi Nagpal
sumber