diff --git a/docs/pages/api/portal.md b/docs/pages/api/portal.md
index c4f4cb7c25995c..8f47b6dbbca1c7 100644
--- a/docs/pages/api/portal.md
+++ b/docs/pages/api/portal.md
@@ -25,7 +25,7 @@ that exists outside the DOM hierarchy of the parent component.
| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
-| children * | node | | The children to render into the `container`. |
+| children | node | | The children to render into the `container`. |
| container | func
| React.Component
| Element | | A node, component instance, or function that returns either. The `container` will have the portal children appended to it. By default, it uses the body of the top-level document object, so it's simply `document.body` most of the time. |
| disablePortal | bool | false | Disable the portal behavior. The children stay within it's parent DOM hierarchy. |
| onRendered | func | | Callback fired once the children has been mounted into the `container`.
This prop will be deprecated and removed in v5, the ref can be used instead. |
diff --git a/packages/material-ui/src/Portal/Portal.d.ts b/packages/material-ui/src/Portal/Portal.d.ts
index 783e1a26c332f8..995037cba06db0 100644
--- a/packages/material-ui/src/Portal/Portal.d.ts
+++ b/packages/material-ui/src/Portal/Portal.d.ts
@@ -4,7 +4,7 @@ export interface PortalProps {
/**
* The children to render into the `container`.
*/
- children: React.ReactNode;
+ children?: React.ReactNode;
/**
* A node, component instance, or function that returns either.
* The `container` will have the portal children appended to it.
diff --git a/packages/material-ui/src/Portal/Portal.js b/packages/material-ui/src/Portal/Portal.js
index e9622e844f676b..67b8a8a9a6af41 100644
--- a/packages/material-ui/src/Portal/Portal.js
+++ b/packages/material-ui/src/Portal/Portal.js
@@ -20,7 +20,7 @@ const useEnhancedEffect = typeof window !== 'undefined' ? React.useLayoutEffect
const Portal = React.forwardRef(function Portal(props, ref) {
const { children, container, disablePortal = false, onRendered } = props;
const [mountNode, setMountNode] = React.useState(null);
- const handleRef = useForkRef(children.ref, ref);
+ const handleRef = useForkRef(React.isValidElement(children) ? children.ref : null, ref);
useEnhancedEffect(() => {
if (!disablePortal) {
@@ -46,10 +46,12 @@ const Portal = React.forwardRef(function Portal(props, ref) {
}, [onRendered, mountNode, disablePortal]);
if (disablePortal) {
- React.Children.only(children);
- return React.cloneElement(children, {
- ref: handleRef,
- });
+ if (React.isValidElement(children)) {
+ return React.cloneElement(children, {
+ ref: handleRef,
+ });
+ }
+ return children;
}
return mountNode ? ReactDOM.createPortal(children, mountNode) : mountNode;
@@ -63,7 +65,7 @@ Portal.propTypes = {
/**
* The children to render into the `container`.
*/
- children: PropTypes.node.isRequired,
+ children: PropTypes.node,
/**
* A node, component instance, or function that returns either.
* The `container` will have the portal children appended to it.
diff --git a/packages/material-ui/src/Portal/Portal.test.js b/packages/material-ui/src/Portal/Portal.test.js
index 3cc62dc83d1239..49d9bce0a55b22 100644
--- a/packages/material-ui/src/Portal/Portal.test.js
+++ b/packages/material-ui/src/Portal/Portal.test.js
@@ -128,10 +128,11 @@ describe('', () => {
it('should render overlay into container (document)', () => {
render(
-
+
+
,
);
- expect(document.querySelectorAll('#test2').length).to.equal(1);
+ expect(document.querySelectorAll('.test2').length).to.equal(2);
});
it('should render overlay into container (DOMNode)', () => {