Skip to content

Commit bd5054a

Browse files
authored
feat: support onAllRemoved (#30)
1 parent ec2f5e8 commit bd5054a

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

src/CSSMotionList.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export interface CSSMotionListProps
4444

4545
/** This will always trigger after final visible changed. Even if no motion configured. */
4646
onVisibleChanged?: (visible: boolean, info: { key: React.Key }) => void;
47+
/** All motion leaves in the screen */
48+
onAllRemoved?: () => void;
4749
}
4850

4951
export interface CSSMotionListState {
@@ -95,16 +97,23 @@ export function genCSSMotionList(
9597
};
9698
}
9799

100+
// ZombieJ: Return the count of rest keys. It's safe to refactor if need more info.
98101
removeKey = (removeKey: React.Key) => {
99-
this.setState(({ keyEntities }) => ({
100-
keyEntities: keyEntities.map(entity => {
101-
if (entity.key !== removeKey) return entity;
102-
return {
103-
...entity,
104-
status: STATUS_REMOVED,
105-
};
106-
}),
107-
}));
102+
const { keyEntities } = this.state;
103+
const nextKeyEntities = keyEntities.map(entity => {
104+
if (entity.key !== removeKey) return entity;
105+
return {
106+
...entity,
107+
status: STATUS_REMOVED,
108+
};
109+
});
110+
111+
this.setState({
112+
keyEntities: nextKeyEntities,
113+
});
114+
115+
return nextKeyEntities.filter(({ status }) => status !== STATUS_REMOVED)
116+
.length;
108117
};
109118

110119
render() {
@@ -113,6 +122,7 @@ export function genCSSMotionList(
113122
component,
114123
children,
115124
onVisibleChanged,
125+
onAllRemoved,
116126
...restProps
117127
} = this.props;
118128

@@ -139,7 +149,11 @@ export function genCSSMotionList(
139149
onVisibleChanged?.(changedVisible, { key: eventProps.key });
140150

141151
if (!changedVisible) {
142-
this.removeKey(eventProps.key);
152+
const restKeysCount = this.removeKey(eventProps.key);
153+
154+
if (restKeysCount === 0 && onAllRemoved) {
155+
onAllRemoved();
156+
}
143157
}
144158
}}
145159
>

tests/CSSMotionList.spec.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,15 @@ describe('CSSMotionList', () => {
106106

107107
it('onVisibleChanged', () => {
108108
const onVisibleChanged = jest.fn();
109+
const onAllRemoved = jest.fn();
109110
const CSSMotionList = genCSSMotionList(false);
110111

111112
const Demo = ({ keys }) => (
112113
<CSSMotionList
113114
motionName="transition"
114115
keys={keys}
115116
onVisibleChanged={onVisibleChanged}
117+
onAllRemoved={onAllRemoved}
116118
>
117119
{({ key, style, className }) => (
118120
<div
@@ -127,13 +129,15 @@ describe('CSSMotionList', () => {
127129
);
128130

129131
const { rerender } = render(<Demo keys={['a']} />);
132+
expect(onAllRemoved).not.toHaveBeenCalled();
130133

131134
act(() => {
132135
jest.runAllTimers();
133136
});
134137

135138
expect(onVisibleChanged).toHaveBeenCalledWith(true, { key: 'a' });
136139
onVisibleChanged.mockReset();
140+
expect(onAllRemoved).not.toHaveBeenCalled();
137141

138142
// Remove
139143
rerender(<Demo keys={[]} />);
@@ -142,5 +146,6 @@ describe('CSSMotionList', () => {
142146
});
143147

144148
expect(onVisibleChanged).toHaveBeenCalledWith(false, { key: 'a' });
149+
expect(onAllRemoved).toHaveBeenCalled();
145150
});
146151
});

0 commit comments

Comments
 (0)