React Checkbox không gửi onChange


136

TLDR: Sử dụng defaultChecked thay vì jsbin hoạt động, đã kiểm tra .

Cố gắng thiết lập một hộp kiểm đơn giản sẽ gạch bỏ văn bản nhãn của nó khi được chọn. Vì một số lý do, handChange không bị sa thải khi tôi sử dụng thành phần này. Bất cứ ai có thể giải thích những gì tôi đang làm sai?

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

Sử dụng:

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

Giải pháp:

Việc sử dụng đã chọn không để giá trị cơ bản thay đổi (rõ ràng) và do đó không gọi trình xử lý onChange. Chuyển sang defaultChecked dường như để khắc phục điều này:

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
Trước hết, tại sao không thêm một onChange this.setState({checked: !this.state.checked})dễ dàng hơn là phải lưu trữ một giá trị. Sau đó, một nhà điều hành ternary trong attrubute đã kiểm tra:checked={this.state.checked ? 'checked': null}
zackify

Đó là cách nó bắt đầu, nhưng dường như không bao giờ cập nhật. Vì vậy, tôi bắt đầu gạt nó ra khỏi đây và để gỡ lỗi những gì không bị sa thải. Lý tưởng nhất sẽ trở lại hình thức đơn giản nhất khi hoàn thành :)
jdarling

Giả sử mountNode của bạn là một nút dom thực tế, bạn sẽ phải sử dụng this.refs.complete.getDOMNode().checked. xem fiddle jsfiddle.net/d10xyqu1
trekForver

Anh ta chỉ có thể sử dụng trạng thái thay vì nhận nút dom: jsfiddle.net/d10xyqu1/1 Nó hoạt động tốt, bạn chắc chắn đã nhầm lẫn một cái gì đó.
zackify

2
Bỏ qua bình luận TLDR - defaultChecked không phải lúc nào cũng là câu trả lời
Chris

Câu trả lời:


207

Để có được trạng thái kiểm tra của hộp kiểm của bạn, đường dẫn sẽ là:

this.refs.complete.state.checked

Cách khác là lấy nó từ sự kiện được truyền vào handleChangephương thức:

event.target.checked

3
handleChange không bao giờ được gọi, không quan trọng nếu bạn nhấp vào hộp kiểm hoặc nhãn, xử lýChange không được gọi là :(.
jdarling

13
Hãy thử sử dụng defaultChecked = {this.state.complete} thay vì "đã kiểm tra" trên đầu vào của bạn.
zbyte

Đó là nó ... Tìm kiếm mãi mãi tìm kiếm và chọc ngoáy. Sẽ cập nhật câu hỏi với câu trả lời làm việc hoàn chỉnh trong trường hợp những người khác cũng chạy qua điều này.
jdarling

Nhưng tại sao - có cùng một vấn đề nhưng bạn nên sử dụng checkedcho các thành phần được kiểm soát: /
Dominic

4
thiết lập checkedcó nghĩa là trạng thái được quản lý bên ngoài thành phần. Khi người dùng nhấp vào, không có gì để gọi handleChangevì không có trạng thái nào được cập nhật. Thay vào đó, bạn sẽ cần lắng nghe onClickvà kích hoạt cập nhật trạng thái ở đó.
zbyte

29

Tốt hơn là không sử dụng ref trong những trường hợp như vậy. Sử dụng:

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

Có một số tùy chọn:

checked đấu với defaultChecked

Cái trước sẽ đáp ứng với cả những thay đổi của nhà nước nhấp chuột. Sau này sẽ bỏ qua những thay đổi trạng thái.

onClick đấu với onChange

Các cựu sẽ luôn kích hoạt trên các nhấp chuột. Cái sau sẽ không kích hoạt khi nhấp nếu checkedthuộc tính có mặt trên inputphần tử.


10

Trong kịch bản bạn KHÔNG muốn sử dụng trình xử lý onChange trên DOM đầu vào, bạn có thể sử dụng thuộc onClicktính thay thế. Điều defaultCheckedkiện có thể để lại trạng thái cố định cho 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>
        )
    }
 }

Tôi hy vọng điều này sẽ giúp ai đó trong tương lai.


10

Nếu bạn có một handleChangechức năng trông như thế này:

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

Bạn có thể tạo một onChangechức năng tùy chỉnh để nó hoạt động như một kiểu nhập văn bản:

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

không phải là handleChangetrên inputnên this.handleChange?
Ardhi

5

Trong trường hợp ai đó đang tìm kiếm một trình xử lý sự kiện phổ quát, đoạn mã sau có thể được sử dụng nhiều hơn hoặc ít hơn (giả sử rằng thuộc tính tên được đặt cho mỗi đầu vào):

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

2

onChange sẽ không gọi handleChange trên thiết bị di động khi sử dụng defaultChecked. Để thay thế, bạn có thể sử dụng onClick và onTouchEnd.

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

1

Trong tài liệu ui, trạng thái của hộp kiểm có thể được tìm nạp là

this.refs.complete.state.switched
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.