{
  "$type": "site.standard.document",
  "canonicalUrl": "https://johnnyreilly.com/posts/mui-react-tree-view-check-children-uncheck-parents",
  "description": "Learn how to use the MUI treeview component with behaviour that selects child nodes when parents are select and deselects parent nodes when children are deselected.",
  "path": "/posts/mui-react-tree-view-check-children-uncheck-parents",
  "publishedAt": "2024-05-25T00:00:00.000Z",
  "site": "at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.publication/3mova7c4nho2b",
  "tags": [
    "react",
    "mui"
  ],
  "textContent": "Every now and then, I need to use a treeview component in a React application. The Material-UI (MUI) library provides a treeview component that is very useful. However, some of the default behaviours of the component differ from that which you typically find in a treeview component. I'm speaking, of course, about node selection. I'm used to a treeview component that, when a parent node is selected, auto selects the child nodes underneath. And by turn, when nodes are deselected, the parent nodes get deselected.\n\nThis post documents how to implement this behaviour with the MUI treeview component.\n\nSince initially writing this, I've learned that it is likely that the kind of behaviour I'm hand-rolling here, will natively land in the component. So, all being well, what follows should become unnecessary! To track native support watch this GitHub issue.\n\n\n\nThe default behaviour and the desired behaviour\n\nBy default, the MUI treeview component checks and unchecks nodes individually. Each node is an island; when a node is selected or deselected, it has no bearing on any other nodes.\n\nWhat I'd rather is some relationship between parent and child nodes during selection / deselection. The behaviour I'd like has the following characteristics:\n\n- when a parent node is selected, all child nodes are selected\n- when a parent node is deselected, all child nodes are deselected\n- when a child node is deselected, the parent node is deselected, and any children are deselected also\n- finally, if all children are selected, the parent node should be selected.\n\nThis is the behaviour that I'm used to in a treeview component. In action it looks like this:\n\nThe code\n\nWe can implement this behaviour by tracking the selected nodes and then determining which nodes should be selected based on the current selection. The code below demonstrates how to do this:\n\nYou'll see above that we're using the RichTreeView component from @mui/x-tree-view. We're setting it to multiSelect and checkboxSelection to allow for multiple selections and to show checkboxes next to each node. We're also tracking the selected nodes in the selectedIds state variable.\n\nThe handleSelectedItemsChange function is called whenever the selection changes. It determines which nodes should be selected based on the current selection and the new selection. The determineIdsToSet function is responsible for this logic.\n\nThe first thing it does is determine if a node is being deselected or selected, by comparing the length of the current selection with the new selection. If a node is being deselected, it finds the parent and child nodes of the deselected node and removes them from the new selection. If a node is being selected, it selects all the children of that node. It also finds the parent node and checks if all child nodes are selected. If they are, it selects the parent node.\n\nConclusion\n\nThe code above demonstrates how to implement a treeview component with parent-child node selection behaviour. This behaviour is, in my opinion, more intuitive and user-friendly than the default behaviour of the MUI treeview component.\n\nYou can also see this code in action on StackBlitz.",
  "title": "MUI React Tree View: check children, uncheck parents"
}