Reputation: 41
i have a problem that my custom checkbox does not work, im not very familliar with React, and can't find any nice spot to learn it more either. Can you checkout my code and tell me what i did wrong ?
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;
Problem is that this component does not get checked, but if i set state to true it does not uncheck, if i install a console log to either handleChange or handleClick, i get console.logged when i click, but only for the first click, im not sure what it means. In another post here i red that it could be problem where on click i check and uncheck so i create an infinite loop, but in that case i should have an infinite loop of console.logs i think. If my code is totally wrong feel free to edit it as you wish, but if its not to much of a hustle try to comment for me changed parts so i better understand whats going on :D
Thanks in advance.
Upvotes: 2
Views: 4384
Reputation: 6805
Problem number one is that you are setting a default prop checked: false
in defaultProps
, and this prop is always being set on the input
via {...attributes}
, so you're effectively always writing that value to false, which is why state changes aren't making any difference.
To fix, you can either get rid of that default prop (and also get rid of setting the state in componentDidMount
), or you could stop throwing all attributes
data into the input
element by default. Up to you.
Now you should be able to see the checkbox get checked / unchecked.
As for changing the property for
to htmlFor
on the label
element, this actually will basically bind the label
element to the input
, so you won't have to implement the onClick
handler for the label
. So once you fix this property, just get rid of your onClick
on the label
entirely. Here's the final code:
All in all, here's what to change:
{...attributes}
from the <input>
element or remove checked
from defaultProps
for
property to htmlFor
on the <label>
elementonClick
event from the <label>
elementUpvotes: 2
Reputation: 1728
Welcome to stackoverflow :)
I think your problem lies in
handleChange() {
this.setState({'checked' : this.state.checked});
}
You're not changing the state but simply want to set it again with the same value. You should be fine when you change it to:
handleChange() {
this.setState({'checked' : !this.state.checked});
}
EDIT:
So the real problem about the input not changing from checked to unchecked is handing over {...attributes}
to the input. This seems to be linked to the "checked" property which interferes with the default checked value of the input element.
Moreover you should use the htmlFor
attribute instead of for
when working with react.
Upvotes: 2
Reputation: 750
This is also an HTML problem, you have to link the label with the input so they trigger together, see solution below, also this might help (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>
Upvotes: -1