Repository: mui/material-ui (TypeScript)
Date: 2020-03-22 16:35:55+00:00
Task type: Bug Fix

Issue:
TreeItem does not allow conditional child
- [x] The issue is present in the latest release.
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Current Behavior 😯

There is an error

## Expected Behavior 🤔

No error

## Steps to Reproduce 🕹

https://codesandbox.io/s/wonderful-pond-89ohe

Steps:

1. Load the sandbox - see that there is nothing displayed.  There should be an error but strangely it is not showing.  If you really want to see it click the refresh 

![image](https://user-images.githubusercontent.com/11292998/76864239-af8ebf00-6858-11ea-8779-a46e2c797a89.png)

![image](https://user-images.githubusercontent.com/11292998/76864245-b1588280-6858-11ea-9e40-e5c65c58dd7e.png)

## Context 🔦

I should be able to conditionally render
```
<TreeItem nodeId="parent" label="parent">
          {props.renderChild && <TreeItem nodeId="parent" label="child" />}
</TreeItem>
```



Issue discussion:
I thought #19849 fixed this but it seems to only fix `TreeView` not `TreeItem`.
https://github.com/mui-org/material-ui/pull/20156

There are more serious bugs than this

Solution patch:
diff --git a/packages/material-ui-lab/src/TreeItem/TreeItem.js b/packages/material-ui-lab/src/TreeItem/TreeItem.js
--- a/packages/material-ui-lab/src/TreeItem/TreeItem.js
+++ b/packages/material-ui-lab/src/TreeItem/TreeItem.js
@@ -338,8 +338,13 @@ const TreeItem = React.forwardRef(function TreeItem(props, ref) {
   };
 
   React.useEffect(() => {
-    const childIds = React.Children.map(children, (child) => child.props.nodeId) || [];
     if (addNodeToNodeMap) {
+      const childIds = [];
+      React.Children.forEach(children, (child) => {
+        if (React.isValidElement(child) && child.props.nodeId) {
+          childIds.push(child.props.nodeId);
+        }
+      });
       addNodeToNodeMap(nodeId, childIds);
     }
   }, [children, nodeId, addNodeToNodeMap]);


Test patch:
diff --git a/packages/material-ui-lab/src/TreeItem/TreeItem.test.js b/packages/material-ui-lab/src/TreeItem/TreeItem.test.js
--- a/packages/material-ui-lab/src/TreeItem/TreeItem.test.js
+++ b/packages/material-ui-lab/src/TreeItem/TreeItem.test.js
@@ -77,6 +77,32 @@ describe('<TreeItem />', () => {
     expect(getIcon('6')).attribute('data-test').to.equal('endIcon');
   });
 
+  it('should allow conditional child', () => {
+    function TestComponent() {
+      const [hide, setState] = React.useState(false);
+
+      return (
+        <React.Fragment>
+          <button data-testid="button" type="button" onClick={() => setState(true)}>
+            Hide
+          </button>
+          <TreeView defaultExpanded={['1']}>
+            <TreeItem nodeId="1" data-testid="1">
+              {!hide && <TreeItem nodeId="2" data-testid="2" />}
+            </TreeItem>
+          </TreeView>
+        </React.Fragment>
+      );
+    }
+    const { getByTestId, queryByTestId } = render(<TestComponent />);
+
+    expect(getByTestId('1')).to.have.attribute('aria-expanded', 'true');
+    expect(getByTestId('2')).to.not.be.null;
+    fireEvent.click(getByTestId('button'));
+    expect(getByTestId('1')).to.not.have.attribute('aria-expanded');
+    expect(queryByTestId('2')).to.be.null;
+  });
+
   it('should treat an empty array equally to no children', () => {
     const { getByTestId } = render(
       <TreeView defaultExpanded={['1']}>