From 3d69bc9d2a59123ec6668b45b892a44314b413ea Mon Sep 17 00:00:00 2001 From: Anurag Hazra Date: Wed, 15 May 2024 07:09:43 +0530 Subject: [PATCH] fix: modal component failing to verify null component (#2174) --- .changeset/soft-tables-provide.md | 5 ++++ .../blade/src/components/Modal/Modal.web.tsx | 25 ++++++------------- .../src/components/Modal/ModalBody.web.tsx | 3 ++- .../src/components/Modal/ModalFooter.web.tsx | 3 ++- .../src/components/Modal/ModalHeader.web.tsx | 3 ++- .../Modal/__tests__/Modal.web.test.tsx | 2 +- .../blade/src/components/Modal/constants.ts | 7 ++++++ .../useVerifyAllowedChildren.ts | 1 + 8 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 .changeset/soft-tables-provide.md create mode 100644 packages/blade/src/components/Modal/constants.ts diff --git a/.changeset/soft-tables-provide.md b/.changeset/soft-tables-provide.md new file mode 100644 index 00000000000..561f738b9a8 --- /dev/null +++ b/.changeset/soft-tables-provide.md @@ -0,0 +1,5 @@ +--- +"@razorpay/blade": patch +--- + +fix(blade): modal component failing to verify null component diff --git a/packages/blade/src/components/Modal/Modal.web.tsx b/packages/blade/src/components/Modal/Modal.web.tsx index 92789a72537..041afb5b45a 100644 --- a/packages/blade/src/components/Modal/Modal.web.tsx +++ b/packages/blade/src/components/Modal/Modal.web.tsx @@ -19,15 +19,16 @@ import { modalResponsiveScreenGap, } from './modalTokens'; import type { ModalProps } from './types'; +import { componentIds } from './constants'; import { castWebType, makeMotionTime, makeSize } from '~utils'; import { BaseBox } from '~components/Box/BaseBox'; import { useTheme } from '~components/BladeProvider'; import { Box } from '~components/Box'; -import { isValidAllowedChildren } from '~utils/isValidAllowedChildren'; import { MetaConstants, metaAttribute } from '~utils/metaAttribute'; import { makeAccessible } from '~utils/makeAccessible'; -import { logger, throwBladeError } from '~utils/logger'; +import { logger } from '~utils/logger'; import { componentZIndices } from '~utils/componentZIndices'; +import { useVerifyAllowedChildren } from '~utils/useVerifyAllowedChildren'; const entry = keyframes` from { @@ -117,20 +118,10 @@ const Modal = ({ }; // Only allow ModalHeader, ModalBody and ModalFooter as children - const validChildren = React.Children.map(children, (child) => { - if ( - isValidAllowedChildren(child, MetaConstants.ModalHeader) || - isValidAllowedChildren(child, MetaConstants.ModalBody) || - isValidAllowedChildren(child, MetaConstants.ModalFooter) - ) { - return child; - } else if (__DEV__) { - throwBladeError({ - message: 'Modal only accepts ModalHeader, ModalBody and ModalFooter as children', - moduleName: 'Modal', - }); - } - return null; + useVerifyAllowedChildren({ + allowedComponents: [componentIds.ModalHeader, componentIds.ModalBody, componentIds.ModalFooter], + children, + componentName: 'Modal', }); return ( @@ -169,7 +160,7 @@ const Modal = ({ isVisible={isVisible} ref={refs.setFloating} > - {validChildren} + {children} diff --git a/packages/blade/src/components/Modal/ModalBody.web.tsx b/packages/blade/src/components/Modal/ModalBody.web.tsx index 0e2ede0f488..50e3faec90d 100644 --- a/packages/blade/src/components/Modal/ModalBody.web.tsx +++ b/packages/blade/src/components/Modal/ModalBody.web.tsx @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import React from 'react'; +import { componentIds } from './constants'; import { assignWithoutSideEffects } from '~src/utils/assignWithoutSideEffects'; import BaseBox from '~components/Box/BaseBox'; import { MetaConstants, metaAttribute } from '~utils/metaAttribute'; @@ -34,7 +35,7 @@ const _ModalBody = ({ children, padding = 'spacing.6' }: ModalBodyProps): React. }; const ModalBody = assignWithoutSideEffects(_ModalBody, { - componentId: MetaConstants.ModalBody, + componentId: componentIds.ModalBody, }); export { ModalBody }; diff --git a/packages/blade/src/components/Modal/ModalFooter.web.tsx b/packages/blade/src/components/Modal/ModalFooter.web.tsx index 4b79143a725..9fd54b622a3 100644 --- a/packages/blade/src/components/Modal/ModalFooter.web.tsx +++ b/packages/blade/src/components/Modal/ModalFooter.web.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { componentIds } from './constants'; import { BaseFooter } from '~components/BaseHeaderFooter/BaseFooter'; import type { BaseFooterProps } from '~components/BaseHeaderFooter/BaseFooter'; import { Box } from '~components/Box'; @@ -23,7 +24,7 @@ const _ModalFooter = (props: ModalFooterProps): React.ReactElement => { }; const ModalFooter = assignWithoutSideEffects(_ModalFooter, { - componentId: MetaConstants.ModalFooter, + componentId: componentIds.ModalFooter, }); export { ModalFooter }; diff --git a/packages/blade/src/components/Modal/ModalHeader.web.tsx b/packages/blade/src/components/Modal/ModalHeader.web.tsx index cadfbfae252..8f94544a0b5 100644 --- a/packages/blade/src/components/Modal/ModalHeader.web.tsx +++ b/packages/blade/src/components/Modal/ModalHeader.web.tsx @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ import { useModalContext } from './ModalContext'; +import { componentIds } from './constants'; import type { BaseHeaderProps } from '~components/BaseHeaderFooter/BaseHeader'; import { makeSize } from '~utils'; import { BaseHeader } from '~components/BaseHeaderFooter/BaseHeader'; @@ -64,7 +65,7 @@ const _ModalHeader = ({ ); }; const ModalHeader = assignWithoutSideEffects(_ModalHeader, { - componentId: MetaConstants.ModalHeader, + componentId: componentIds.ModalHeader, }); export { ModalHeader }; diff --git a/packages/blade/src/components/Modal/__tests__/Modal.web.test.tsx b/packages/blade/src/components/Modal/__tests__/Modal.web.test.tsx index 559e1e1dcb0..2ddc01c56a2 100644 --- a/packages/blade/src/components/Modal/__tests__/Modal.web.test.tsx +++ b/packages/blade/src/components/Modal/__tests__/Modal.web.test.tsx @@ -233,7 +233,7 @@ describe('Modal', () => { ); }; expect(() => renderWithTheme()).toThrow( - '[Blade: Modal]: Modal only accepts ModalHeader, ModalBody and ModalFooter as children', + '[Blade: Modal]: Only `ModalHeader, ModalBody, ModalFooter` components are accepted in `Modal` children', ); mockConsoleError.mockRestore(); }); diff --git a/packages/blade/src/components/Modal/constants.ts b/packages/blade/src/components/Modal/constants.ts new file mode 100644 index 00000000000..01201308a89 --- /dev/null +++ b/packages/blade/src/components/Modal/constants.ts @@ -0,0 +1,7 @@ +const componentIds = { + ModalHeader: 'ModalHeader', + ModalBody: 'ModalBody', + ModalFooter: 'ModalFooter', +}; + +export { componentIds }; diff --git a/packages/blade/src/utils/useVerifyAllowedChildren/useVerifyAllowedChildren.ts b/packages/blade/src/utils/useVerifyAllowedChildren/useVerifyAllowedChildren.ts index 6067984d1c5..fec7df23cb5 100644 --- a/packages/blade/src/utils/useVerifyAllowedChildren/useVerifyAllowedChildren.ts +++ b/packages/blade/src/utils/useVerifyAllowedChildren/useVerifyAllowedChildren.ts @@ -13,6 +13,7 @@ const useVerifyAllowedChildren = (props: { const { children, componentName, allowedComponents } = props; if (__DEV__) { React.Children.forEach(children, (child) => { + if (!React.isValidElement(child)) return; const isValidChild = child && allowedComponents.includes(getComponentId(child)!); if (!isValidChild) { throwBladeError({