From 67f59f62f3896eb284eb8de3325198f073e34c15 Mon Sep 17 00:00:00 2001 From: afc163 Date: Fri, 1 Jul 2022 10:50:15 +0800 Subject: [PATCH] fix: Collapse not working using custom component as panel --- src/Collapse.tsx | 26 ++++++++++++++++++++++---- tests/index.spec.tsx | 28 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/Collapse.tsx b/src/Collapse.tsx index 3c5f647..81d6615 100644 --- a/src/Collapse.tsx +++ b/src/Collapse.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import shallowEqual from 'shallowequal'; import toArray from 'rc-util/lib/Children/toArray'; import CollapsePanel from './Panel'; -import { CollapseProps, CollapsibleType } from './interface'; +import type { CollapseProps, CollapsibleType } from './interface'; function getActiveKeysArray(activeKey: React.Key | React.Key[]) { let currentActiveKey = activeKey; @@ -78,10 +78,22 @@ class Collapse extends React.Component { if (!child) return null; const { activeKey } = this.state; - const { prefixCls, openMotion, accordion, destroyInactivePanel: rootDestroyInactivePanel, expandIcon, collapsible } = this.props; + const { + prefixCls, + openMotion, + accordion, + destroyInactivePanel: rootDestroyInactivePanel, + expandIcon, + collapsible, + } = this.props; // If there is no key provide, use the panel order as default key const key = child.key || String(index); - const { header, headerClass, destroyInactivePanel, collapsible: childCollapsible } = child.props; + const { + header, + headerClass, + destroyInactivePanel, + collapsible: childCollapsible, + } = child.props; let isActive = false; if (accordion) { isActive = activeKey[0] === key; @@ -89,7 +101,7 @@ class Collapse extends React.Component { isActive = activeKey.indexOf(key) > -1; } - const mergeCollapsible: CollapsibleType = childCollapsible ?? collapsible; + const mergeCollapsible: CollapsibleType = childCollapsible ?? collapsible; const props = { key, @@ -112,6 +124,12 @@ class Collapse extends React.Component { return child; } + Object.keys(props).forEach((propName: keyof typeof props) => { + if (typeof props[propName] === 'undefined') { + delete props[propName]; + } + }); + return React.cloneElement(child, props); }; diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 408b532..2c4371b 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -485,6 +485,34 @@ describe('collapse', () => { expect(collapse.find('.custom-child').getDOMNode().innerHTML).toBe('custom-child'); }); + // https://github.com/ant-design/ant-design/issues/36327 + // https://github.com/ant-design/ant-design/issues/6179 + // https://github.com/react-component/collapse/issues/73#issuecomment-323626120 + it('should support custom component', () => { + const PanelElement = (props) => ( + +

test

+
+ ); + const collapse = mount( + + + + second + + , + ); + expect(collapse.find('.rc-collapse-content-active').length).toBe(1); + expect(collapse.find('.rc-collapse-content').hasClass('rc-collapse-content-active')).toBe(true); + expect(collapse.find('.rc-collapse-header').at(0).text()).toBe('collapse 1'); + expect(collapse.find('.rc-collapse-header').at(0).find('.arrow').length).toBe(1); + collapse.find('.rc-collapse-header').at(0).simulate('click'); + expect(collapse.find('.rc-collapse-content-active').length).toBe(0); + expect(collapse.find('.rc-collapse-content').hasClass('rc-collapse-content-inactive')).toBe( + true, + ); + }); + describe('collapsible', () => { it('default', () => { const collapse = mount(