Skip to content

Conversation

@zombieJ
Copy link
Member

@zombieJ zombieJ commented Nov 27, 2025

ref https://github.com/react-component/tooltip/pull/509/files#r2567392550

Summary by CodeRabbit

发布说明

  • 新功能
    • 触发器组件现在支持渲染函数模式,允许通过接收弹出窗口的打开状态来动态呈现内容,提供更灵活的自定义选项。

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 27, 2025

过程分析

Trigger 组件扩展了 children 属性,现在支持渲染函数模式。当 children 为函数时,接收包含 open 布尔值的对象,允许组件根据弹出框的打开状态动态渲染子元素。同步添加了相应测试验证此功能。

变更

分类 / 文件 变更摘要
Trigger 组件类型定义
src/index.tsx
修改 TriggerProps.children 类型,支持 React.ReactElement 或接收 { open: boolean } 的渲染函数;引入 memoized 渲染逻辑,根据 mergedOpen 状态动态计算子节点
Trigger 功能测试
tests/basic.test.jsx
新增测试用例验证 Trigger 支持函数型 children,确保渲染函数能正确接收并使用 open 状态参数

序列图

sequenceDiagram
    participant Parent as 父组件
    participant Trigger
    participant RenderFn as children 函数
    participant DOM
    
    Parent->>Trigger: 传入 children 函数 + popupVisible={true}
    Trigger->>Trigger: 计算 mergedOpen = true
    Trigger->>RenderFn: 调用 children({ open: true })
    RenderFn-->>Trigger: 返回 ReactElement
    Trigger->>DOM: 渲染子元素
    DOM-->>Parent: 显示结果
Loading

审查工作量估计

🎯 2 (简单) | ⏱️ ~10 分钟

  • 关注点
    • 验证 React.Children.only() 在函数型 children 返回多个元素时的错误处理
    • 确认 memoization 逻辑不会导致意外的重渲染行为
    • 检查渲染函数签名与文档是否一致

可能相关的 PR

建议审查者

  • MadCcc

诗歌

🐰 一只兔子在述说,
children 函数来舞动,
open 状态轻轻传,
渲染之花绽放明,
灵活组件焕新生!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地总结了主要变更:向Trigger组件的children属性添加renderProps支持,这与代码更改和测试用例完全一致。
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch renderProps

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @zombieJ, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant enhancement to the Trigger component by enabling its children prop to accept a render function. This allows developers to create more flexible and dynamic UI components that can react to the trigger's open state directly within their children's rendering logic. The changes involve updating the component's type definitions, refactoring the children processing to support this new pattern, and adding comprehensive test coverage to ensure its reliability.

Highlights

  • Render Props Support for Children: The children prop of the TriggerProps interface now supports a render function signature, allowing it to receive the open state of the component.
  • Dynamic Children Handling: The internal logic for handling children in the generateTrigger function has been updated to detect if children is a function and, if so, execute it with the current open state, ensuring dynamic rendering.
  • New Test Coverage: A new test case has been added to tests/basic.test.jsx to specifically verify that the children render prop correctly receives and utilizes the open state.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Nov 27, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.42%. Comparing base (ff89971) to head (907e798).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #591      +/-   ##
==========================================
+ Coverage   96.41%   96.42%   +0.01%     
==========================================
  Files          17       17              
  Lines         948      952       +4     
  Branches      278      281       +3     
==========================================
+ Hits          914      918       +4     
  Misses         34       34              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for render props for the children prop, allowing the child component to be aware of the trigger's open state. The implementation in src/index.tsx is clean and uses React.useMemo effectively to handle the new render prop functionality. The type definitions have been updated accordingly, and a new test case has been added to verify the feature. Overall, this is a great addition. I have one suggestion to enhance the test coverage for this new feature.

Comment on lines +371 to +385
describe('children renderProps', () => {
it('should get current open', () => {
const { container } = render(
<Trigger
popupVisible={true}
popup={<span>Hello!</span>}
>
{({ open }) => <button>{String(open)}</button>}
</Trigger>,
);

const button = container.querySelector('button');
expect(button.textContent).toBe('true');
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The added test case is a good start for verifying the render prop functionality. To make the tests more comprehensive, I suggest covering both controlled and uncontrolled component scenarios, as well as state transitions from open to close and vice-versa. This will ensure the open state is correctly propagated to the child in all situations.

  describe('children renderProps', () => {
    it('should get current open state and update for controlled component', () => {
      const { container, rerender } = render(
        <Trigger popupVisible={false} popup={<span>Hello!</span>}>
          {({ open }) => <button>{String(open)}</button>}
        </Trigger>,
      );

      const button = container.querySelector('button');
      expect(button.textContent).toBe('false');

      rerender(
        <Trigger popupVisible={true} popup={<span>Hello!</span>}>
          {({ open }) => <button>{String(open)}</button>}
        </Trigger>,
      );

      expect(button.textContent).toBe('true');
    });

    it('should update with action for uncontrolled component', () => {
      const { container } = render(
        <Trigger action={['click']} popup={<span>Hello!</span>}>
          {({ open }) => <button>{String(open)}</button>}
        </Trigger>,
      );

      const button = container.querySelector('button');
      expect(button.textContent).toBe('false');

      fireEvent.click(button);
      act(() => jest.runAllTimers());

      expect(button.textContent).toBe('true');

      fireEvent.click(button);
      act(() => jest.runAllTimers());

      expect(button.textContent).toBe('false');
    });
  });

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/basic.test.jsx (1)

371-385: 测试覆盖了基本功能,但建议增加更多场景。

当前测试验证了 popupVisible={true} 时 render-prop 能正确接收 { open: true }。建议添加以下测试用例以提高覆盖率:

  1. 测试 open 状态变化时子组件能正确更新
  2. 测试非受控模式下通过 action 触发状态变化的场景
  describe('children renderProps', () => {
    it('should get current open', () => {
      const { container } = render(
        <Trigger
          popupVisible={true}
          popup={<span>Hello!</span>}
        >
          {({ open }) => <button>{String(open)}</button>}
        </Trigger>,
      );

      const button = container.querySelector('button');
      expect(button.textContent).toBe('true');
    });
+
+    it('should update when open state changes', () => {
+      const { container, rerender } = render(
+        <Trigger
+          popupVisible={false}
+          popup={<span>Hello!</span>}
+        >
+          {({ open }) => <button>{String(open)}</button>}
+        </Trigger>,
+      );
+
+      expect(container.querySelector('button').textContent).toBe('false');
+
+      rerender(
+        <Trigger
+          popupVisible={true}
+          popup={<span>Hello!</span>}
+        >
+          {({ open }) => <button>{String(open)}</button>}
+        </Trigger>,
+      );
+
+      expect(container.querySelector('button').textContent).toBe('true');
+    });
  });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff89971 and 907e798.

📒 Files selected for processing (2)
  • src/index.tsx (2 hunks)
  • tests/basic.test.jsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
src/index.tsx (2)

53-55: 类型定义清晰,支持 render-prop 模式。

类型定义正确地扩展了 children 以支持函数形式,参数 { open: boolean } 能够让子组件响应 Trigger 的打开状态。


313-322: 实现正确,使用 useMemo 是合适的选择。

使用 useMemo 来处理 render-prop 是正确的,因为当 mergedOpen 状态变化时需要重新计算子节点。React.Children.only 确保了单子节点约束。

一个小提示:如果使用方传入内联函数作为 children(如 {() => <Button />}),每次父组件渲染都会导致 useMemo 重新计算。建议在文档中说明,对于需要优化性能的场景,使用方可以用 useCallback 包裹函数。

@zombieJ zombieJ merged commit 6c6da53 into master Nov 27, 2025
10 checks passed
@zombieJ zombieJ deleted the renderProps branch November 27, 2025 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants