Skip to content

Commit 95cb1db

Browse files
authored
fix: first render should not provide a hidden content (#16)
* 2.4.2 * fix: First render is not forceRender
1 parent 0450ffb commit 95cb1db

File tree

6 files changed

+78
-11
lines changed

6 files changed

+78
-11
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,4 @@ es
2828
yarn.lock
2929
package-lock.json
3030
coverage/
31-
.doc
32-
tsconfig.json
31+
.doc

.prettierrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"singleQuote": true,
55
"tabWidth": 2,
66
"proseWrap": "never",
7-
"trailingComma": "all"
7+
"trailingComma": "all",
8+
"arrowParens": "avoid"
89
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rc-motion",
3-
"version": "2.4.1",
3+
"version": "2.4.2",
44
"description": "React lifecycle controlled motion library",
55
"keywords": [
66
"react",

src/CSSMotion.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import findDOMNode from 'rc-util/lib/Dom/findDOMNode';
55
import { fillRef } from 'rc-util/lib/ref';
66
import classNames from 'classnames';
77
import { getTransitionName, supportTransition } from './util/motion';
8-
import {
8+
import type {
99
MotionStatus,
10-
STATUS_NONE,
1110
MotionEventHandler,
1211
MotionEndEventHandler,
13-
MotionPrepareEventHandler,
12+
MotionPrepareEventHandler} from './interface';
13+
import {
14+
STATUS_NONE,
1415
STEP_PREPARE,
1516
STEP_START,
1617
} from './interface';
@@ -156,6 +157,13 @@ export function genCSSMotion(
156157
props,
157158
);
158159

160+
// Record whether content has rended
161+
// Will return null for un-rendered even when `removeOnLeave={false}`
162+
const renderedRef = React.useRef(mergedVisible);
163+
if (mergedVisible) {
164+
renderedRef.current = true;
165+
}
166+
159167
// ====================== Refs ======================
160168
const originRef = useRef(ref);
161169
originRef.current = ref;
@@ -177,7 +185,7 @@ export function genCSSMotion(
177185
// Stable children
178186
if (mergedVisible) {
179187
motionChildren = children({ ...mergedProps }, setNodeRef);
180-
} else if (!removeOnLeave) {
188+
} else if (!removeOnLeave && renderedRef.current) {
181189
motionChildren = children(
182190
{ ...mergedProps, className: leavedClassName },
183191
setNodeRef,

tests/CSSMotion.spec.tsx

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import React from 'react';
66
import { act } from 'react-dom/test-utils';
77
import classNames from 'classnames';
88
import { mount } from './wrapper';
9-
import RefCSSMotion, { genCSSMotion, CSSMotionProps } from '../src/CSSMotion';
9+
import type { CSSMotionProps } from '../src/CSSMotion';
10+
import RefCSSMotion, { genCSSMotion } from '../src/CSSMotion';
1011

1112
describe('CSSMotion', () => {
1213
const CSSMotion = genCSSMotion({
@@ -267,7 +268,7 @@ describe('CSSMotion', () => {
267268

268269
test(
269270
'without ref',
270-
React.forwardRef((props) => <div {...props} />),
271+
React.forwardRef(props => <div {...props} />),
271272
);
272273

273274
test(
@@ -552,7 +553,7 @@ describe('CSSMotion', () => {
552553
let lockResolve: Function;
553554
const onAppearPrepare = jest.fn(
554555
() =>
555-
new Promise((resolve) => {
556+
new Promise(resolve => {
556557
lockResolve = resolve;
557558
}),
558559
);
@@ -606,4 +607,46 @@ describe('CSSMotion', () => {
606607
wrapper.setProps({ forceRender: false });
607608
expect(wrapper.find('.motion-box')).toHaveLength(0);
608609
});
610+
611+
it('render null on first when removeOnLeave is false', () => {
612+
const wrapper = mount(
613+
<CSSMotion
614+
motionName="bamboo"
615+
removeOnLeave={false}
616+
leavedClassName="removed"
617+
visible={false}
618+
>
619+
{({ style, className }) => (
620+
<div style={style} className={classNames('motion-box', className)} />
621+
)}
622+
</CSSMotion>,
623+
);
624+
625+
expect(wrapper.find('.motion-box')).toHaveLength(0);
626+
627+
// Visible
628+
wrapper.setProps({ visible: true });
629+
act(() => {
630+
jest.runAllTimers();
631+
wrapper.update();
632+
});
633+
expect(wrapper.find('.motion-box')).toHaveLength(1);
634+
635+
// Hide again
636+
wrapper.setProps({ visible: false });
637+
act(() => {
638+
jest.runAllTimers();
639+
640+
const transitionEndEvent = new Event('transitionend');
641+
((wrapper
642+
.find('.motion-box')
643+
.instance() as any) as HTMLElement).dispatchEvent(transitionEndEvent);
644+
645+
jest.runAllTimers();
646+
647+
wrapper.update();
648+
});
649+
expect(wrapper.find('.motion-box')).toHaveLength(1);
650+
expect(wrapper.find('.motion-box').hasClass('removed')).toBeTruthy();
651+
});
609652
});

tsconfig.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"target": "esnext",
4+
"moduleResolution": "node",
5+
"baseUrl": "./",
6+
"jsx": "preserve",
7+
"declaration": true,
8+
"skipLibCheck": true,
9+
"esModuleInterop": true,
10+
"paths": {
11+
"@/*": ["src/*"],
12+
"@@/*": ["src/.umi/*"],
13+
"rc-menu": ["src/index.tsx"]
14+
}
15+
}
16+
}

0 commit comments

Comments
 (0)