refactor: migrate CSSMotionList to FC#82
Conversation
|
@QDyanbing is attempting to deploy a commit to the afc163's projects Team on Vercel. A member of the Team first needs to authorize it. |
Walkthrough
ChangesCSSMotionList hooks 迁移
预估代码审查工作量🎯 4 (Complex) | ⏱️ ~45 minutes 可能相关的 PR
建议审查者
诗
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #82 +/- ##
==========================================
+ Coverage 98.09% 98.68% +0.58%
==========================================
Files 11 11
Lines 421 456 +35
Branches 121 137 +16
==========================================
+ Hits 413 450 +37
+ Misses 7 6 -1
+ Partials 1 0 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review
This pull request refactors the CSSMotionList component from a class-based component to a functional component using React Hooks. The reviewer provided highly valuable feedback to optimize this migration, which includes: avoiding double renders and layout thrashing by adjusting state during render instead of using a dependency-less useIsomorphicLayoutEffect; removing unsafe Ref mutations from the useState updater function to ensure Concurrent Mode safety; switching to useEffect for non-blocking callbacks; and adding reference equality checks in helper functions to prevent unnecessary comparisons.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/CSSMotionList.tsx`:
- Around line 93-102: shallowEqualKeyObject is too permissive: it only compares
values and can treat objects with different keys as equal, which can retrigger
setKeyEntities in CSSMotionList’s layout effect. Update shallowEqualKeyObject to
verify that target contains each key from origin before comparing values, and
make the comparison stable for NaN values so identical KeyObject metadata does
not cause unnecessary updates.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5960b965-f4a0-48a3-8804-38c188e4f65a
📒 Files selected for processing (1)
src/CSSMotionList.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/CSSMotionList.spec.tsx`:
- Around line 177-191: The CSSMotionList test does not actually verify the
children(props, ref) ref-compatibility path, since rendering still passes even
when ref is undefined. Update the CSSMotionList spec around the
component={false} case to assert the ref is explicitly provided to the child
render function and/or observed on the rendered element, using the CSSMotionList
render prop signature and the existing motion-box assertion to cover the real
branch.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7cc4cd4c-342e-4993-8e5d-1ef73f89ce87
📒 Files selected for processing (2)
src/CSSMotionList.tsxtests/CSSMotionList.spec.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/CSSMotionList.tsx
| it('should support children ref when component is false', () => { | ||
| const CSSMotionList = genCSSMotionList(false); | ||
|
|
||
| const { container } = render( | ||
| <CSSMotionList motionName="transition" component={false} keys={['a']}> | ||
| {({ key }, ref) => ( | ||
| <div ref={ref as React.Ref<HTMLDivElement>} className="motion-box"> | ||
| {key} | ||
| </div> | ||
| )} | ||
| </CSSMotionList>, | ||
| ); | ||
|
|
||
| expect(container.children).toHaveLength(1); | ||
| expect(container.querySelector('.motion-box')).toHaveTextContent('a'); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
这个用例还没有真正覆盖到 children(props, ref) 分支。
现在即使第二个参数是 undefined,<div ref={ref as ...}> 也照样能渲染成功,所以这里的断言只能证明文本渲染正常,抓不住 ref 兼容分支的回归。
建议补一个显式断言
it('should support children ref when component is false', () => {
const CSSMotionList = genCSSMotionList(false);
+ let receivedRef: React.Ref<HTMLDivElement> | undefined;
const { container } = render(
<CSSMotionList motionName="transition" component={false} keys={['a']}>
{({ key }, ref) => (
- <div ref={ref as React.Ref<HTMLDivElement>} className="motion-box">
+ (() => {
+ receivedRef = ref as React.Ref<HTMLDivElement>;
+ return (
+ <div ref={receivedRef} className="motion-box">
+ {key}
+ </div>
+ );
+ })()
- {key}
- </div>
)}
</CSSMotionList>,
);
expect(container.children).toHaveLength(1);
expect(container.querySelector('.motion-box')).toHaveTextContent('a');
+ expect(receivedRef).toBeTruthy();
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it('should support children ref when component is false', () => { | |
| const CSSMotionList = genCSSMotionList(false); | |
| const { container } = render( | |
| <CSSMotionList motionName="transition" component={false} keys={['a']}> | |
| {({ key }, ref) => ( | |
| <div ref={ref as React.Ref<HTMLDivElement>} className="motion-box"> | |
| {key} | |
| </div> | |
| )} | |
| </CSSMotionList>, | |
| ); | |
| expect(container.children).toHaveLength(1); | |
| expect(container.querySelector('.motion-box')).toHaveTextContent('a'); | |
| it('should support children ref when component is false', () => { | |
| const CSSMotionList = genCSSMotionList(false); | |
| let receivedRef: React.Ref<HTMLDivElement> | undefined; | |
| const { container } = render( | |
| <CSSMotionList motionName="transition" component={false} keys={['a']}> | |
| {({ key }, ref) => ( | |
| (() => { | |
| receivedRef = ref as React.Ref<HTMLDivElement>; | |
| return ( | |
| <div ref={receivedRef} className="motion-box"> | |
| {key} | |
| </div> | |
| ); | |
| })() | |
| )} | |
| </CSSMotionList>, | |
| ); | |
| expect(container.children).toHaveLength(1); | |
| expect(container.querySelector('.motion-box')).toHaveTextContent('a'); | |
| expect(receivedRef).toBeTruthy(); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/CSSMotionList.spec.tsx` around lines 177 - 191, The CSSMotionList test
does not actually verify the children(props, ref) ref-compatibility path, since
rendering still passes even when ref is undefined. Update the CSSMotionList spec
around the component={false} case to assert the ref is explicitly provided to
the child render function and/or observed on the rendered element, using the
CSSMotionList render prop signature and the existing motion-box assertion to
cover the real branch.
背景
Ant Design issue ant-design/ant-design#58404 正在清理依赖中的 React class component。
@rc-component/motion中的CSSMotionList仍使用 class component,本 PR 将其迁移为函数组件,不引入公开 API 变化。改动内容
CSSMotionList从 class component 迁移为函数组件。diffKeys与移除状态过滤。onVisibleChanged、onAllRemoved的触发行为。component默认值、motion props 拆分以及 children ref 兼容分支。验证
npm testnpm run lint(仅保留既有 warning)npm run lint:tscnpm run compile(仅保留既有 warning)git diff --check HEADSummary by CodeRabbit