Conversation
📝 WalkthroughWalkthrough引入完整的 IndexBar 组件:包含 SectionList 集成、手势驱动的 Indicator(触摸映射到索引并触发回调)、主题化样式、文档、演示与测试文件,并将组件与类型导出到公共 API。 Changes
Sequence DiagramsequenceDiagram
participant User as User
participant Indicator as Indicator (组件)
participant Pan as PanResponder
participant IndexBar as IndexBar (组件)
participant SectionList as SectionList
User->>Indicator: 触摸/拖动(locationY)
Indicator->>Pan: 转交手势事件
Pan->>Indicator: 返回 locationY
Indicator->>Indicator: 计算并更新 activeIndex/isInteracting
Indicator->>IndexBar: 调用 onChange(selectedKey)
IndexBar->>IndexBar: 计算目标 section 索引
IndexBar->>SectionList: scrollToLocation(目标 section)
SectionList->>SectionList: 渲染并定位到该 section
Indicator->>Indicator: 高亮选中项并显示缩放文本
User->>Indicator: 松手
Indicator->>Indicator: 延迟取消 isInteracting
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
Summary of ChangesHello @lqr131115, 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! 此拉取请求引入了一个全新的 Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new IndexBar component, which is a great addition for navigating long lists. The implementation is well-structured, with separate components for the main list and the indicator. I've found a few issues to address:
- A critical bug that causes scrolling to the wrong section when the provided
sectionsare not sorted. - An incorrect type definition that leads to a conflict.
- Some opportunities for improving type safety and preventing potential memory leaks in the
Indicatorcomponent.
After these changes are addressed, this will be a solid new feature. Good work!
components/index-bar/PropsType.tsx
Outdated
| export interface IndexBarSectionData { | ||
| key: string | ||
| title: string | ||
| data: string[] |
There was a problem hiding this comment.
The IndexBarSectionData interface includes a data: string[] property. This conflicts with the data property from React Native's SectionListData type. A section object ends up with two data properties of incompatible types, which is a type error and can cause confusion. The data property should be removed from IndexBarSectionData as it's already defined in SectionListData.
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Fix all issues with AI agents
In `@components/index-bar/demo/basic.tsx`:
- Around line 6-18: The demo's `sections` generation uses Math.random (in the
const sections block in components/index-bar/demo/basic.tsx), which makes
snapshot tests flaky; replace the non-deterministic randomization with a
deterministic approach (e.g., a fixed dataset, a simple pseudo-random generator
with a hard-coded seed, or an array of predetermined counts) so that `data` and
`randomCount` are stable across renders and rnDemoTest snapshots; ensure the
change targets the `sections` creation logic so titles/keys remain the same
shape but deterministic.
In `@components/index-bar/index.en-US.md`:
- Line 36: 文档中 `data` 字段的类型标注不正确:将文档里第 36 行的 `data` 类型从 `any[]` 更新为 `string[]`
so it matches the implementation of `IndexBarSectionData.data` in
`PropsType.tsx`; ensure the doc entry for the `data` field (labelled "Section
data list") uses `string[]` and restore parity with the
`IndexBarSectionData.data` type.
In `@components/index-bar/index.tsx`:
- Around line 35-42: memoAvailableIndexes currently sorts section keys but
_onIndexChange uses the clicked index as if it were the original sections order,
causing wrong target indices; fix by preserving mapping to the original section
index (e.g., have memoAvailableIndexes produce items with { key, originalIndex }
or keep the sorted keys but in _onIndexChange resolve the clicked key to the
original section index via sections.findIndex(s => s.key === clickedKey)) and
then use that originalIndex when calling the scroll/section change logic; update
references to memoAvailableIndexes and _onIndexChange accordingly so clicks
always map to the correct sections entry.
In `@components/index-bar/PropsType.tsx`:
- Around line 4-9: The interface IndexBarSectionData currently types the data
field as string[] but the documentation (index.zh-CN.md) says any[]; update
IndexBarSectionData to use a more general type (e.g., data: any[] or make the
interface generic like IndexBarSectionData<T> { data: T[] }) so the type matches
docs and supports flexible item types; ensure related usages of
IndexBarSectionData (and any function/type declarations referencing it) are
updated to the chosen generic or any[] form.
In `@components/index-bar/style/index.tsx`:
- Around line 77-90: The styles activeIndicatorTextContainer and
indicatorScaleTextContainer currently use borderRadius: '50%' which is ignored
on native; change them to use numeric widths/heights and set borderRadius to
half the size (e.g. set width and height and borderRadius = width/2) so the
containers render as circles on iOS/Android; remove the // `@ts-ignore` comments
and ensure indicatorScaleTextContainer’s padding/transform and right offset
still produce the intended layout after you pick the explicit size.
- Around line 59-64: The inline style uses transform: [{ translateY: '-50%' }]
with a `@ts-ignore` which is unsupported on native RN 0.67; remove the `@ts-ignore`
and replace the percentage translate with a numeric approach (either compute the
pixel offset via onLayout and set translateY to a number, or use absolute
positioning with top and height-based calculation) in the same style object
where transform is defined (the style containing top: '50%', justifyContent,
alignItems); leave borderRadius: '50%' as-is since string percentages are
allowed.
🧹 Nitpick comments (6)
components/index-bar/index.zh-CN.md (1)
20-27: 表格格式不一致表头行(第20-21行)没有首尾管道符,但数据行(第22-27行)有首尾管道符。建议统一格式。
📝 建议的修复
-属性 | 说明 | 类型 | 默认值 -----|-----|------|------ -| sections | 分组数据,必需 | `SectionListData<any, IndexBarSectionData>[]` | - | -| onIndexChange | 索引变化时的回调函数 | `(key: string, index: number) => void` | - | -| animated | 滚动时是否使用动画 | `boolean` | `false` | -| showIndicator | 是否显示索引指示器 | `boolean` | `true` | -| style | 自定义容器样式 | `StyleProp<ViewStyle>` | - | -| styles | 语义化结构 style | [IndexBarStyle](`#indexbarstyle-语义化样式`) | - | +| 属性 | 说明 | 类型 | 默认值 | +| ---- | ---- | ---- | ------ | +| sections | 分组数据,必需 | `SectionListData<any, IndexBarSectionData>[]` | - | +| onIndexChange | 索引变化时的回调函数 | `(key: string, index: number) => void` | - | +| animated | 滚动时是否使用动画 | `boolean` | `false` | +| showIndicator | 是否显示索引指示器 | `boolean` | `true` | +| style | 自定义容器样式 | `StyleProp<ViewStyle>` | - | +| styles | 语义化结构 style | [IndexBarStyle](`#indexbarstyle-语义化样式`) | - |components/index-bar/Indicator.tsx (2)
7-7: 使用具体类型替代any
activeIndex的类型应该是number而不是any,以获得更好的类型安全性。♻️ 建议的修复
- const [activeIndex, setActiveIndex] = useState<any>(0) + const [activeIndex, setActiveIndex] = useState<number>(0)
46-55: 建议将魔法数字提取为常量
200毫秒的延迟时间在onPanResponderRelease和onPanResponderTerminate中重复使用,建议提取为命名常量以提高可读性和可维护性。♻️ 建议的修复
+const INTERACTION_END_DELAY = 200 + const Indicator: React.FC<IndicatorProps> = ({ indexes, styles, onChange }) => { // ... onPanResponderRelease: () => { setTimeout(() => { setInteracting(false) - }, 200) + }, INTERACTION_END_DELAY) }, onPanResponderTerminate: () => { setTimeout(() => { setInteracting(false) - }, 200) + }, INTERACTION_END_DELAY) },components/index-bar/demo/basic.md (2)
17-26: 变量名遮蔽问题第 20 行的
index参数遮蔽了第 17 行外层的index变量。建议使用不同的变量名以提高可读性:♻️ 建议修改
- const sections = Array.from({length: 26}, (_, index) => { + const sections = Array.from({length: 26}, (_, i) => { - const key = String.fromCharCode(65 + index); + const key = String.fromCharCode(65 + i); const randomCount = Math.floor(Math.random() * 3) + 3; - const data = Array.from({length: randomCount}, (_, index) => `Content ${key}${index}`); + const data = Array.from({length: randomCount}, (_, j) => `Content ${key}${j}`);
27-28: 分号位置异常
return语句后的分号被放在了单独一行,这是不常见的格式。建议将其移到同一行:♻️ 建议修改
- return <IndexBar sections={sections}/> - ; + return <IndexBar sections={sections} />;components/index-bar/index.tsx (1)
102-110: keyExtractor 对非字符串 item 的处理当
item不是字符串类型时(例如对象),item + index会产生"[object Object]0"这样的键值,可能导致重复键或难以调试的问题。建议增加类型安全处理:
♻️ 建议修改
const memoKeyExtractor = useCallback( (item: string, index: number) => { if (typeof keyExtractor === 'function') { return keyExtractor(item, index) } - return item + index + return typeof item === 'string' ? `${item}-${index}` : `item-${index}` }, [keyExtractor], )
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@components/index-bar/index.zh-CN.md`:
- Line 38: The docs list the prop "data" as `any[]` but the code's PropsType.tsx
defines IndexBarSectionData.data as `string[]`; update the Chinese index-bar
docs (components/index-bar/index.zh-CN.md) to reflect `string[]` for the data
column, and make the same change in the English counterpart so documentation
matches the implementation (search for IndexBarSectionData and the "data" row in
the table to locate the entry).
🧹 Nitpick comments (1)
components/index-bar/Indicator.tsx (1)
6-7:timeRef类型定义可以更精确
setTimeout在 React Native 环境中返回的是ReturnType<typeof setTimeout>类型。使用number类型虽然在运行时工作正常,但类型不够精确。♻️ 建议的优化
- const timeRef = useRef<number>(0) + const timeRef = useRef<ReturnType<typeof setTimeout> | null>(null)同时更新 clearTimeout 调用:
const _onPanResponderFinish = useCallback(() => { if (timeRef.current) { clearTimeout(timeRef.current) } - timeRef.current = setTimeout(() => { + timeRef.current = setTimeout(() => { setInteracting(false) }, 200) }, [])
|
建议使用 @lqr131115 老弟要上生产线的代码就会要求高一些 加油🫶 |
First of all, thank you for your contribution! :-)
Please makes sure that these checkboxes are checked before submitting your PR, thank you!
npm run lintand fix those errors before submitting in order to keep consistent code style.Extra checklist:
if isBugFix :
elif isNewFeature :
Summary by CodeRabbit