I have a working nested checkbox example I am working on implementing into my application. The logic for the checkboxs is functional enough to cover theses 7 cases
- Scenario - No children, no parent selected
- Select the parent -> select the parent and all children
- Select a child -> select that child and its parent
- Scenario - All children and the parent selected
- Select the parent -> deselect the parent and all children
- Select a child -> deselect only that child
- Scenario - Some children and the parent selected
- Select the parent -> select all unselected children
- Select a child -> select that child, parent remains selected
- Deselect last child -> deselect the child and deselect the parent
The issue I am running into is that in scenarios when the child is selected or deselected, the parent checkbox's state is updated, but the actual visual change of the checkbox isn't happening.
From my code:
<Checkbox
disableRipple
edge="start"
checked={sub.checked}
onChange={() =>
this.handleCheckClick(sub.id, parentIndex)
}
/>
The Material-UI <Checkbox />
component is inside of a list of items, and each item has a subsequent list of items with their own <Checkbox />
components respectively. When I select the parent checkbox of the list the state changes properly through that handleCheckClick()
method, and the state is updated properly, and the visual update happens as you would think.
When the child is clicked, an ideal situation would be that the parent is then selected, which it is in the react component's state, but the visual aspect of the change isn't taking place despite the checkbox's checked
state being mapped to state.
The interesting part is that if I use a native input like this:
<input
type="checkbox"
disableRipple
edge="start"
checked={sub.checked}
onChange={() =>
this.handleCheckClick(sub.id, parentIndex)
}
/>
The correct behavior is both displayed visually, but also in state (like it already was). I am not sure if this is an error specific to Material-UI, or a race condition, or something else happening, but I do know that the logic in the handleCheckClick()
function is sound as changes are being displayed properly in the react state.
You actually have a warning indicating what is going on:
Warning: A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/docs/forms.html#controlled-components
The issue is that you are not initializing the checked
state in createSubscriptions
(see code below), so initially sub.checked
is undefined
. This causes Material-UI to treat the checkbox as uncontrolled , so specifying the checked
state later has no effect.
function createSubscriptions() {
const statusSet = ["Processing", "Completed", "Submitted", "Error"];
const quantity = (faker.random.number() % 10) + 1;
const subscriptions = [];
let x = 0;
while (x < quantity) {
subscriptions.push({
id: faker.random.uuid(),
name: faker.lorem.words(),
description: faker.lorem.sentence(),
created: faker.date.past(),
status: statusSet[faker.random.number() % 4],
checked: false, // ADDING THIS FIXES IT
geoJson: {
features: createGeoJson()
}
});
x += 1;
}
return subscriptions;
}
Alternatively, you can handle this at the point of rendering the Checkbox:
<Checkbox
disableRipple
edge="start"
checked={sub.checked || false}
onChange={() =>
this.handleCheckClick(sub.id, parentIndex)
}
/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.