What I'm experiencing is what seems like onClick listeners accumulating across renders and firing more and more times as I toggle a checkbox.
I'm mapping over an array to generate the checkboxes, like this:
const list = permissions[cat].map((p) => {
// map the role's permissions to the checked state of the "all" permission checkboxes
const checked = _.findWhere(role.permissions, {id: p.id}) ? true : false;
return <CheckBox key={p.id}
checked={checked}
label={p.operation}
onChange={e => this.togglePermission(p.id)} />;
});
the checkbox looks like this:
const CheckBox = ({ checked, label, onChange }) => (
<Input
checked={checked}
type="checkbox"
label={prettyPrint(label)}
onChange={onChange} />
);
and this.togglePermssion looks like this:
togglePermission(id) {
this.props.togglePermissionOnRole(id);
}
What's happening is that when I toggle a checkbox, the redux action is dispatched and the component is re-rendered. When I toggle a checkbox again (the same or another), this.togglePermission is called again multiple times. As I toggle more checkboxes, the amount of times it's executed seems to grow exponentially.
Any ideas as to why this behaviour happens?
I actually figured this out - turns out it was Rollbar's JS snippet the whole time.
Related
I'm working on a React app with a button to reset a form. When the user clicks the "Reset" button, all the states revert to their original values. But a checkmark remains selected even after all the other data clears. It does appear to reset the state, but the checkmark is still visible and confusing to the user. I understand that defaultChecked is read on the initial load, but the checkmark remains even if I remove defaultChecked completely, so I'm not sure where the problem is. I suspect the solution might involve onChange, but I haven't been able to get that to work. Any help appreciated.
const [checked, setChecked] = useState(false);
const clearSearch = () => {
setResults([]);
setQuery("");
setFormat("");
setChecked(false);
}
<label>
<input
type="checkbox"
id="searchAll"
defaultChecked={checked}
onChange={() => setChecked(!checked)}
/>
Search all formats
</label>
<button className="btn btn-danger"
onClick={event => {
event.preventDefault();
clearSearch();
}}>
Reset
</button>
App.js on GitHub https://github.com/irene-rojas/loc/blob/master/src/App.js
Your checkbox is actually an uncontrolled input, which probably isn't what you want (it usually isn't in React). That is because, although you've got the onChange event wired up to a handler which sets state, you're not reading back from that state into the input. Except in the defaultChecked attribute - which doesn't control whether it's actually checked or not.
You need to use the checked attribute, which for a checkbox is essentially equivalent to the value attribute of a text or numeric input:
<input
type="checkbox"
id="searchAll"
checked={checked}
onChange={() => setChecked(!checked)}
/>
(I've removed your defaultChecked attribute, as I don't think you want it - but feel free to put it back in if you do. The important thing is having a checked attribute that reads from the checked state value.)
I have a form with state handled in a context. within the form I have a checkbox component which I am trying to have its state handled within the context. So when I submit the form the checkbox returns a Boolean whether it is checked or not. I'm having trouble with the event handler triggering the checkbox.
I have a number of textfields in the form which are behaving as expected and their values can be seen in the Db once the form is submitted.
Within the checkbox component the actual input is hidden for styling purposes. So the user will be clicking on the label(which is styled to look like a checkbox) or a secondary label (acting as a label)
I'd like it so that when a user clicks on either of the labels the checkbox is triggered. I had the onClick on the checkbox input but seeing as it's display is hidden the user cannot trigger the event.
If I put the onClick on either of the labels or a parent element my onChange functions e.target is pointing to the wrong location.
Is there a way to pass in the the input as the e.target? if the onClick event is on the outer div?
onChange (within RecordForm.js)
const onChange = (e) => {
setRecord({ ...record, [e.target.name]: e.target.value });
};
Checkbox.js
const CheckBox2 = ({ value, label, name, onChange }) => {
return (
<CheckBoxContainer onClick={onChange}>
<LabelContainer>
<CheckboxInput
type='checkbox'
value={value}
name={name}
/>
<CheckBoxLabel>
<Tick className='Tick' />
</CheckBoxLabel>
</LabelContainer>
<VisibleLabel>{label}</VisibleLabel>
</CheckBoxContainer>
);
};
export default CheckBox2;
I have a set of checkboxes which the user checks to create some filters. The user submits the form where they activate the filters. This works fine however if the user goes back to the filterContainer the checkboxes do not keep their state and all checkboxes are unchecked.
How can check the checked checkboxes when the filter page is loaded.
If this was standard JS I would simply grab each dom element (with the correct id and then set the attribute to checked) Although I don't see a way of doing this in React.
Here is the code
Age data is simply an array and the handleClick function just sends the data to the store.
const ageData = [18+,18-35,36-50, 50+]
<div className="filter__group-container">
<h3>Age</h3>
{ageData.map((item, index) =>[<div className="filter__group-item-container" key={index}>
<CheckBox checked={need to send a boolean here somehow}
handleClick={() =>this.handleClick({
'id':item.id,
'name': 'age_group_ids'
})}
key={index}
id={'age:' + item.id} />
<label key={item.description + index}>{item.description}</label> </div> ])}
</div>
this?
const checkedIds = []
<CheckBox checked={checkedIds.includes(item.id)} ..
I have implemented in React a webpage with 3 input fields, each one with the properties of
onChange={this.handleChange} and disabled={this.isDisabled()}
The desired behavior is that when an input field contains 2 digits, the focus will be moved to the next input field.
As long as the field doesn't contain 2 digits, the fields next to must be disabled.
What actually happens, when I type the second digit in the first field, it runs the handleChange function, that function checks whether the field contains 2 digits, find out that yes, and moves the focus to the next input field.
But the next field is disabled! (because the isDisabled function didn't run yet!)
So the cursor doesn't move..
I want to change the order of the happenings, or any other way to solve it.
Do you have any suggestions?
The problem is that this.isDisabled() runs immediately in render but this.handleChange runs on click and most possibly doesn't change the state thus no rerender.
You sholdn't run function on next input, you should pass true or false to its disabled prop. Just make handleChange update the state which defines which fields are disabled. And pass that state to your inputs accordingly.
I had faced the same issue a few days back. My approach was however using react states and focusing the input by its id, that was fetched from state;
So first we make a input - id map for our convenience. And use document.getElementById(this.state.active).focus() function. We change our state via our change handler.
render() {
this.setInputFocus();
return (
<div className="App">
<input id="1" onChange={this.onChange} />
<input id="2" onChange={this.onChange} />
<input id="3" onChange={this.onChange} />
</div>
);
}
setInputFocus = () => {
if (document.getElementById(this.state.active)) {
document.getElementById(this.state.active).focus();
}
};
onChange = e => {
if (e.target.value.length === 2) {
this.setState({ active: this.state.active + 1 });
}
};
Here is a full code that somewhat solves the issue
I have the following code for radio selection control:
<Radio
inline
id={item}
enter code herename="stackedRadios"
value={item}
label={item}
checked={this.state.checked == item}
onChange={this.handleChange.bind(this, item, quesId)}
/>
The handle change function is :
handleChange (value, quesId) {
this.setState({checked: value})
}
In the handle change function what I am trying to print the value on console but nothing is printed on console.
Now what I want is to get the selected value from the radio but failing to get so. Please help with the same.
Since you've used bind with 2 args, event which is normally the first arg, will be the third.
handleChange (value, quesId, event) {
this.setState({ checked: event.target.checked })
}
If you don't need the first two values then don't bind. Also you shouldn't use bind inside of render as this causes the Radio component to have new props every render even if nothing changed, since a new function is created every render.