React复选框未将其状态设置为在单击标签时选中

时间:2019-01-05 10:47:26

标签: javascript reactjs

我有一个问题,我的自定义复选框不起作用, 我对React不太熟悉,也找不到更好的地方来学习它。您可以签出我的代码并告诉我我做错了什么吗?

    import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

class Checkbox extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      checked: false
    };
    this.handleChange = this.handleChange.bind(this);
    this.checkbox = React.createRef();
    this.handleClick = () => {
      this.checkbox.current.click();
    };
  }

  componentDidMount() {
    this.setState({'checked' : this.props.checked});
  }

  handleChange() {
    this.setState({'checked' : !this.state.checked});
  }

  render() {
    let {
      className,
      label,
      ...attributes
    } = this.props;

    const classes = classNames(
      'checkbox',
      className,
    );

    return (
      <div className={classes}>
        <input id="checkbox_1" type="checkbox" checked={this.state.checked} onChange={this.handleChange} {...attributes} ref={this.checkbox} />
        <label for="checkbox_1" className="checkbox-label" onClick={this.handleClick}>{label}</label>
      </div>
    );
  }
}

Checkbox.defaultProps = {
  checked: false,
  className: '',
  label: null
};

Checkbox.propTypes = {
  checked: PropTypes.bool,
  className: PropTypes.string,
  onClick: PropTypes.func,
  label: PropTypes.string
};

export default Checkbox;

问题在于此组件未得到检查,但是如果我将state设置为true,则不会取消选中该组件,如果我将控制台日志安装到handleChange或handleClick,则单击时会得到console.logged,但仅适用于第一次点击,我不确定这是什么意思。我在这里的另一篇文章中提到,单击并取消选中可能会出现问题,因此我创建了一个无限循环,但是在这种情况下,我认为应该有一个console.logs无限循环。 如果我的代码是完全错误的,请随意编辑它,但是如果它没有太多麻烦,请尝试为我注释一下已更改的部分,以便我更好地了解发生了什么:D

谢谢。

3 个答案:

答案 0 :(得分:2)

欢迎来到stackoverflow:)

我认为您的问题出在

handleChange() {
  this.setState({'checked' : this.state.checked});
}

您不需要更改状态,而只是想再次使用相同的值进行设置。将其更改为:

handleChange() {
  this.setState({'checked' : !this.state.checked});
}

编辑:

因此,有关输入未从选中更改为未选中的真正问题是将{...attributes}移交给了输入。这似乎与“ checked”属性有关,该属性会干扰输入元素的默认选中值。

此外,在使用react时,应使用htmlFor属性而不是for

答案 1 :(得分:1)

第一个问题是您正在checked: false中设置默认道具defaultProps,并且始终通过input{...attributes}上设置此道具,所以您有效地总是将该值写为false,这就是为什么状态更改没有任何区别的原因。

要解决此问题,您可以放弃该默认属性(也可以摆脱在componentDidMount中设置状态),也可以停止将所有attributes数据丢入{{1} }元素的默认值。由你决定。

现在,您应该可以看到该复选框已选中/未选中。

关于将input元素上的属性for更改为htmlFor,实际上这实际上会将label元素绑定到label,所以您无需为input实现onClick处理程序。因此,一旦您修复了此属性,就完全摆脱label上的onClick。这是最终的代码:

总而言之,这是要更改的内容

  1. label元素中删除{...attributes},或者从<input> 中删除checked
  2. defaultProps元素上的for属性更改为htmlFor
  3. <label>元素中删除onClick事件

答案 2 :(得分:-1)

这也是一个HTML问题,您必须将标签与输入链接在一起,以便它们一起触发,请参阅下面的解决方案,这也可能有帮助(https://www.w3schools.com/tags/tag_label.asp

<h1>checkbox demo</h1>

<input type="checkbox">
<label>I don't activate the checkbox</label>

<hr>

<input type="checkbox" id="checkbox_1">
<label for="checkbox_1">I activate the checkbox</label>

<hr>

<label>
	<input type="checkbox">
	I also activate the checkbox
</label>