简体   繁体   中英

Material-UI Nested Checkbox selection doesn't render change to parent in DOM

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

编辑嵌套复选框材质 UI

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM