React Checkbox not sending onChange

怎甘沉沦 提交于 2019-11-27 04:21:30

问题


TLDR: Use defaultChecked instead of checked, working jsbin.

Trying to setup a simple checkbox that will cross out its label text when it is checked. For some reason handleChange is not getting fired when I use the component. Can anyone explain what I'm doing wrong?

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

Usage:

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

Solution:

Using checked doesn't let the underlying value change (apparently) and thus doesn't call the onChange handler. Switching to defaultChecked seems to fix this:

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

回答1:


To get the checked state of your checkbox the path would be:

this.refs.complete.state.checked

The alternative is to get it from the event passed into the handleChange method:

event.target.checked



回答2:


It's better not to use refs in such cases. Use:

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

There are some options:

checked vs defaultChecked

The former would respond to both state changes and clicks. The latter would ignore state changes.

onClick vs onChange

The former would always trigger on clicks. The latter would not trigger on clicks if checked attribute is present on input element.




回答3:


In the scenario you would NOT like to use the onChange handler on the input DOM, you can use the onClick property as an alternative. The defaultChecked, the condition may leave a fixed state for 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>
        )
    }
 }

I hope this helps someone in the future.




回答4:


If you have a handleChange function that looks like this:

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

You can create a custom onChange function so that it acts like an text input would:

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



回答5:


onChange will not call handleChange on mobile when using defaultChecked. As an alternative you can can use onClick and onTouchEnd.

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



回答6:


In material ui, state of checkbox can be fetched as

this.refs.complete.state.switched


来源:https://stackoverflow.com/questions/26615779/react-checkbox-not-sending-onchange

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!