Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add lazyRender prop for Collapsible #2104

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions content/show/collapsible/index-en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ import { Collapsible, Button } from '@douyinfe/semi-ui';
| duration | Time of animation execution | number | 250 | - |
| isOpen | Toggle whether to expand the content area | boolean | `false` | - |
| keepDOM | Whether to keep the hidden panel in DOM tree, destroyed by default | boolean | `false` | 0.25.0 |
| lazyRender | Used with keepDOM, when true, the component will not be rendered when mounting | boolean | `true` | 2.24 |
| motion | Toggle whether to turn on animation | Motion | `true` | - |
| onMotionEnd | Animation end callback | () => void | - | - |
| reCalcKey | When reCalcKey changes, the height of children will be reset. Used for optimize dynamic content rendering. | number \| string | - | 1.5.0 |
Expand Down
1 change: 1 addition & 0 deletions content/show/collapsible/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ import { Collapsible, Button } from '@douyinfe/semi-ui';
| fade | 是否开启淡入淡出 | boolean | false | 2.21.0 |
| isOpen | 是否展开内容区域 | boolean | `false` | - |
| keepDOM | 是否保留隐藏的面板 DOM 树,默认销毁 | boolean | `false` | 0.25.0 |
| lazyRender | 配合 keepDOM 使用,为 true 时挂载时不会渲染组件 | boolean | `true` | 2.24 |
| motion | 是否开启动画 | boolean | `true` | - |
| onMotionEnd | 动画结束的回调 | () => void | - | - |
| reCalcKey | 当 reCalcKey 改变时,将重新计算子节点的高度,用于优化动态渲染时的计算 | number \| string | - | 1.5.0 |
Expand Down
44 changes: 44 additions & 0 deletions packages/semi-ui/collapsible/__test__/collapsible.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { clear } from 'jest-date-mock';
import { Collapsible } from '../../index';

function getCollapsible(props, children) {
return (<Collapsible {...(props || {})}>
{children ? children : <div className='collapsible-test-content'>hello</div>}
</Collapsible>);
}

describe('collapsible', () => {
beforeEach(() => {
// Avoid `attachTo: document.body` Warning
const div = document.createElement('div');
div.setAttribute('id', 'container');
document.body.appendChild(div);
clear();
});

it('keepDOM = true', async () => {
let component = getCollapsible({ keepDOM: true, motion: false });
let collapsible = mount(component, { attachTo: document.getElementById('container') })
expect(collapsible.exists(`.collapsible-test-content`)).toEqual(false);
// set true
collapsible.setProps({ isOpen: true });
collapsible.update(); // 必须调用一次update
expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true);
collapsible.setProps({ isOpen: false });
collapsible.update(); // 必须调用一次update
expect(collapsible.exists(`.collapsible-test-content`)).toEqual(false);
});

it('keepDOM + lazyRender = false', () => {
let component = getCollapsible({ keepDOM: true, lazyRender: false });
let collapsible = mount(component);
expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true);
// set true
collapsible.setProps({ isOpen: true });
collapsible.update(); // 必须调用一次update
expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true);
collapsible.setProps({ isOpen: false });
collapsible.update(); // 必须调用一次update
expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true);
});
});
4 changes: 3 additions & 1 deletion packages/semi-ui/collapsible/_story/collapsible.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class DemoDOM extends React.Component {
return (
<div>
<Button onClick={() => this.toggle()}>显示更多</Button>
<Collapsible keepDOM isOpen={isOpen}>
<Collapsible keepDOM lazyRender={!!this.props.lazyRender} isOpen={isOpen}>
{collapsed}
</Collapsible>
</div>
Expand All @@ -91,6 +91,8 @@ class DemoDOM extends React.Component {

export const KeepDom = () => <DemoDOM />;

export const LazyRender = () => <DemoDOM lazyRender={true} />;

class DefaultOpen extends React.Component {
state = {
isOpen: true,
Expand Down
10 changes: 7 additions & 3 deletions packages/semi-ui/collapsible/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface CollapsibleProps extends CollapsibleFoundationProps {
isOpen?: boolean;
duration?: number;
keepDOM?: boolean;
lazyRender?: boolean;
className?: string;
style?: React.CSSProperties;
collapseHeight?: number;
Expand All @@ -42,6 +43,7 @@ class Collapsible extends BaseComponent<CollapsibleProps, CollapsibleState> {
duration: 250,
motion: true,
keepDOM: false,
lazyRender: true,
collapseHeight: 0,
fade: false
})
Expand Down Expand Up @@ -157,9 +159,8 @@ class Collapsible extends BaseComponent<CollapsibleProps, CollapsibleState> {
isChildrenInRenderTree = () => {
if (this.domRef.current) {
return this.domRef.current.offsetHeight > 0;
} else {
return false;
}
return false;
}

render() {
Expand All @@ -173,6 +174,9 @@ class Collapsible extends BaseComponent<CollapsibleProps, CollapsibleState> {
const wrapperCls = cls(`${cssClasses.PREFIX}-wrapper`, {
[`${cssClasses.PREFIX}-transition`]: this.props.motion && this.state.isTransitioning
}, this.props.className);

const shouldRender = (this.props.keepDOM && !this.props.lazyRender) || this.props.collapseHeight !== 0 || this.state.visible || this.props.isOpen;

return (
<div
className={wrapperCls}
Expand All @@ -193,7 +197,7 @@ class Collapsible extends BaseComponent<CollapsibleProps, CollapsibleState> {
id={this.props.id}
>
{
(this.props.keepDOM || this.props.collapseHeight !== 0 || this.state.visible || this.props.isOpen) && this.props.children
shouldRender && this.props.children
}
</div>
</div>
Expand Down
Loading