diff --git a/packages/mui-material/src/ButtonGroup/ButtonGroup.js b/packages/mui-material/src/ButtonGroup/ButtonGroup.js index c9d548175044aa..da933aa31579e2 100644 --- a/packages/mui-material/src/ButtonGroup/ButtonGroup.js +++ b/packages/mui-material/src/ButtonGroup/ButtonGroup.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import clsx from 'clsx'; import { unstable_composeClasses as composeClasses } from '@mui/base/composeClasses'; import { alpha } from '@mui/system'; +import { getValidReactChildren } from '@mui/utils'; import capitalize from '../utils/capitalize'; import styled from '../styles/styled'; import useThemeProps from '../styles/useThemeProps'; @@ -256,9 +257,12 @@ const ButtonGroup = React.forwardRef(function ButtonGroup(inProps, ref) { ], ); - const getButtonPositionClassName = (index, childrenParam) => { + const validChildren = getValidReactChildren(children); + const childrenCount = validChildren.length; + + const getButtonPositionClassName = (index) => { const isFirstButton = index === 0; - const isLastButton = index === React.Children.count(childrenParam) - 1; + const isLastButton = index === childrenCount - 1; if (isFirstButton && isLastButton) { return ''; @@ -282,13 +286,12 @@ const ButtonGroup = React.forwardRef(function ButtonGroup(inProps, ref) { {...other} > - {React.Children.map(children, (child, index) => { - if (!React.isValidElement(child)) { - return child; - } - + {validChildren.map((child, index) => { return ( - + {child} ); diff --git a/packages/mui-utils/src/getValidReactChildren.ts b/packages/mui-utils/src/getValidReactChildren.ts new file mode 100644 index 00000000000000..6a2d5912347563 --- /dev/null +++ b/packages/mui-utils/src/getValidReactChildren.ts @@ -0,0 +1,13 @@ +import * as React from 'react'; + +/** + * Gets only the valid children of a component, + * and ignores any nullish or falsy child. + * + * @param children the children + */ +export default function getValidReactChildren(children: React.ReactNode) { + return React.Children.toArray(children).filter((child) => + React.isValidElement(child), + ) as React.ReactElement[]; +} diff --git a/packages/mui-utils/src/index.ts b/packages/mui-utils/src/index.ts index 1ad27fb44d5f21..8968bcc49f694a 100644 --- a/packages/mui-utils/src/index.ts +++ b/packages/mui-utils/src/index.ts @@ -32,6 +32,7 @@ export { getNormalizedScrollLeft as unstable_getNormalizedScrollLeft, } from './scrollLeft'; export { default as usePreviousProps } from './usePreviousProps'; +export { default as getValidReactChildren } from './getValidReactChildren'; export { default as visuallyHidden } from './visuallyHidden'; export { default as integerPropType } from './integerPropType'; export { default as internal_resolveProps } from './resolveProps'; diff --git a/test/regressions/fixtures/ButtonGroup/DifferentChildren.js b/test/regressions/fixtures/ButtonGroup/DifferentChildren.js index 44f107dcc0badd..5f231c6d1058a0 100644 --- a/test/regressions/fixtures/ButtonGroup/DifferentChildren.js +++ b/test/regressions/fixtures/ButtonGroup/DifferentChildren.js @@ -5,6 +5,8 @@ import Stack from '@mui/material/Stack'; import Tooltip from '@mui/material/Tooltip'; export default function DifferentChildren() { + const falsyCondition = 1 === 2; + return ( {/* It has one button with href which is rendered as anchor tag */} @@ -35,6 +37,13 @@ export default function DifferentChildren() { + + {/* Conditional elements */} + + + + {falsyCondition ? : undefined} + ); }