perf: improve perf#180
Conversation
SafeDep Report SummaryPackage Details
This report is generated by SafeDep Github App |
|
Important Review skippedToo many files! This PR contains 159 files, which is 59 over the limit of 100. You can disable this status message by setting the
Walkthrough该 PR 大量新增 React Native 最佳实践与规则文档,并在应用中引入基于 Zustand 的播放器存储(usePlayerStore),将若干搜索/标签页更新为并发模式(useDeferredValue / startTransition),改造 LocalTrackList 为 forwardRef 并新增布局动画准备调用,同时简化全局键盘动画处理与提供者结构。 Changes
Sequence Diagram(s)sequenceDiagram
participant Root as App Root (/src/app/_layout.tsx)
participant Store as usePlayerStore (Zustand)
participant Orpheus as Orpheus (native player)
participant TrackSvc as trackService (JS API)
participant UI as UI Components (Player, Pages)
Root->>Store: initialize()
Store->>Orpheus: query currentTrack & index
Orpheus-->>Store: currentTrack info
alt currentTrack exists
Store->>TrackSvc: getTrackByUniqueKey(currentTrack.id)
TrackSvc-->>Store: Track (or error)
Store-->>UI: set internalTrack & orpheusTrack
else no currentTrack
Store-->>UI: clear internalTrack
end
UI->>Store: read selectors (useCurrentTrack / useCurrentTrackId / useIsCurrentTrack)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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 |
There was a problem hiding this comment.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/playlist/local/[id].tsx (1)
29-78: 延迟查询的实现方向正确,但需补充关键最佳实践。
useDeferredValue与startSearch结合确实能保持输入的响应性,但需注意:
网络请求优化:
useDeferredValue本身不会减少网络调用。由于useSearchTracksInPlaylist直接使用deferredQuery,应在fetch 层添加防抖、缓存或请求取消机制,否则仍会频繁请求。推荐补充:
- 为结果列表组件添加
memo包装,避免不必要的重渲染- 当
searchQuery !== deferredQuery时添加视觉反馈(如灰显结果),指示数据正在更新
🤖 Fix all issues with AI agents
In @.agents/skills/react-native-best-practices/references/bundle-analyze-js.md:
- Around line 155-162: The snippet in rspack.config.js uses hard tabs for
indentation; replace tabs with spaces in the JavaScript code block so formatting
is consistent with Markdown lint rules — update the lines containing
RsdoctorRspackPlugin, the plugins array and the process.env.RSDOCTOR expression
to use spaces instead of tabs (e.g., two or two/consistent spaces) across the
code block.
In
@.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md:
- Around line 107-113: The code block containing the export default array
(starts with "export default [" and includes the plugins/rules object and
'no-barrel-files/no-barrel-files') uses hard tabs for indentation which violates
MD010; open that code block and replace each tab character with spaces (use the
repository's markdown indentation style, e.g., 2 or 4 spaces consistently) so
the lines for plugins, rules, and the rule entry are space-indented instead of
tab-indented.
- Around line 77-80: The fenced code block that currently contains the Require
cycle warning (the block starting with "Warning: Require cycle:
components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts") is
missing a language tag; update that code fence to include a language identifier
(for example `text` or `tsx`) so MarkdownLint rule MD040 is satisfied — locate
the fenced block and change the opening backticks from ``` to ```text (or
```tsx) accordingly.
In
@.agents/skills/react-native-best-practices/references/bundle-native-assets.md:
- Around line 33-38: The markdown contains multiple fenced code blocks without a
language tag (e.g., the blocks starting with "assets/",
"android/app/build/outputs/bundle/release/", "ios/RNAssets.xcassets/", "App
bundle contains:", "iPhone 15 Pro receives:", and "Variant: MyApp-<UUID>.ipa");
update each of these backtick-fenced blocks to use a language identifier of
"text" (i.e., replace ``` with ```text) so markdownlint MD040 is satisfied and
rendering/linting is consistent across the document.
In @.agents/skills/react-native-best-practices/references/bundle-r8-android.md:
- Around line 168-170: Update the header text "### Library Specific Rules" to
use a hyphenated form "### Library-specific Rules" to correct the grammar;
locate the header string in the markdown (the line containing "Library Specific
Rules") and replace it with the hyphenated version.
In
@.agents/skills/react-native-best-practices/references/bundle-tree-shaking.md:
- Around line 19-35: The code blocks contain hard tab characters triggering
MD010; replace all tab characters with spaces inside the shown snippets (and
other similar code blocks) so lint passes — specifically edit the
metro.config.js snippet (the config.transformer.getTransformOptions function)
and the babel.config.js snippet (the module.exports preset entry that sets
disableImportExportTransform) to use spaces instead of tabs throughout.
In
@.agents/skills/react-native-best-practices/references/js-animations-reanimated.md:
- Line 52: The markdown has fenced code blocks missing language identifiers
(reporting markdownlint MD040); update each offending fence (the triple-backtick
blocks) in
.agents/skills/react-native-best-practices/references/js-animations-reanimated.md
by adding an explicit language tag (e.g., text, bash, jsx) after the opening ```
for the code blocks noted (the three unlabelled fenced blocks) so lint passes.
In
@.agents/skills/react-native-best-practices/references/js-lists-flatlist-flashlist.md:
- Around line 83-99: The example component BetterList uses index.toString() in
the keyExtractor which contradicts the guidance to avoid array indices; update
BetterList to expect items with a stable identifier (e.g., id or key) and change
the keyExtractor to return that stable id (for example keyExtractor={item =>
item.id.toString() || item.key}) or, if the list is truly static, add an
explicit comment stating the index fallback is only for immutable static lists;
apply the same change to the other example referenced (lines ~125-130) and
update the items prop description to require a stable id field.
In
@.agents/skills/react-native-best-practices/references/native-turbo-modules.md:
- Around line 108-137: Code blocks for the Swift and Objective-C++ examples use
hard tab characters for indentation; replace all tab characters with spaces (use
2 or 4 spaces per indent consistently) across the code blocks so Markdown
renders correctly—update the Swift example in AwesomeLibrary.swift (extension
AwesomeLibrary and func multiply) and the ObjC++ bridge in AwesomeLibrary.mm
(implementation AwesomeLibrary, RCT_EXPORT_MODULE(), and the
RCT_EXTERN_METHOD(multiply:b:)) by running a "replace tabs with spaces" in your
editor or linter and verify no remaining \t characters remain in those snippets.
- Around line 13-34: The Swift examples use hard tab characters for indentation;
update the code blocks for the sync example (the `@objc` func heavyWork() ->
NSNumber implementation) and the async example (the `@objc` func
heavyWork(resolve:reject:) implementation that uses DispatchQueue.global().async
and resolve/reject) to replace tabs with spaces so indentation is consistent
across both snippets, keeping Swift-style 2 (or project standard) spaces per
indent and preserving line breaks and punctuation.
In
@.agents/skills/react-native-best-practices/references/native-view-flattening.md:
- Around line 17-18: 文件中的多处行(例如包含 <Tab1 /> 和 <Tab2 /> 的行,以及评论提到的其他段落)使用了硬制表符,触发
MD010。请将这些硬 tab 全部替换为空格(例如 2 或 4 个空格,遵循项目约定),确保所有 Markdown 行首与行中缩进不含 \t 字符并重新运行
lint 验证;检查并修复所有列出的区块(包括第 26-27、54-69、77-79、123-156、165-170、175-177
所示区域)以消除所有硬制表符引用,如 <Tab1 /> 和 <Tab2 /> 所在行。
In @.agents/skills/vercel-react-native-skills/rules/js-hoist-intl.md:
- Around line 18-22: 这些行使用了硬制表符(tabs)触发 markdownlint 的 MD010;在包含
Intl.NumberFormat
的片段(formatter、Intl.NumberFormat(...)、formatter.format(amount)、<Text>)将行缩进中的所有
tab 替换为等价数量的空格以保持一致缩进风格,并在同一规则适用的其他位置(第 30-31, 35, 43-44, 56)做相同处理,确认保存后重新运行
lint。
In
@.agents/skills/vercel-react-native-skills/rules/list-performance-callbacks.md:
- Line 5: Update the YAML frontmatter `tags` entry that currently uses
placeholder values `tag1, tag2` by replacing them with relevant, descriptive
tags (for example: list, performance, callbacks, memoization) so the document's
metadata accurately reflects its content; edit the `tags:` line in the markdown
frontmatter to contain the new comma-separated tags.
- Around line 32-42: The current useCallback defines onPress outside renderItem
but references item.id which is out of scope; fix by making onPress accept id
(useCallback((id) => handlePress(id), [handlePress])) and pass that to
LegendList/Item, or alternatively move the id-specific handler into the Item
component (e.g., Item uses its own useCallback(() => onPress(item.id), [onPress,
item.id]) while the parent onPress only depends on handlePress); update
references to onPress, handlePress, LegendList, and Item accordingly.
In
@.agents/skills/vercel-react-native-skills/rules/list-performance-function-references.md:
- Around line 82-84: 示例中使用了 ES2023 的 toSorted()(sortedTlds =
tlds.toSorted(...)),这在部分 React Native/Hermes 版本上可能不受支持;请将其替换为先复制原数组再调用 sort
的兼容写法:创建一个新数组副本(使用扩展运算符复制 tlds)然后在副本上调用 Array.prototype.sort 并传入原有的比较函数(基于
a.name.localeCompare(b.name)),确保 sortedTlds 为新实例且不直接变更原始 tlds。
In
@.agents/skills/vercel-react-native-skills/rules/navigation-native-navigators.md:
- Around line 29-193: 文件中的多个 Markdown 代码块使用了硬 Tab 导致 MD010 报告;在包含示例的代码块(例如函数/组件名
App、Layout、TabLayout、以及 JSX 片段含
Stack.Navigator、Tab.Navigator、Stack.Screen、NativeTabs.Trigger 等)中将所有硬制 Tab
字符替换为一致的空格缩进(例如 2 个或 4 个空格),对所有代码块执行相同替换并保存,然后重新运行 markdownlint/MD010 验证修复。
In @.agents/skills/vercel-react-native-skills/rules/ui-measure-views.md:
- Around line 22-43: 代码块第22-43行使用硬Tab导致 markdownlint MD010 报错;请在该代码片段中将所有硬 Tab
替换为空格(建议每级缩进用两个或四个空格),检查并修复涉及到 useRef<View>(null), useLayoutEffect, onLayout 和
LayoutChangeEvent 的缩进以保持一致性,确保返回的 JSX <View ref={ref} onLayout={onLayout}>
区块及内部子节点也使用空格缩进以通过 lint 校验。
In @.agents/skills/vercel-react-native-skills/rules/ui-menus.md:
- Around line 21-39: 代码块中使用了硬 Tab 导致 markdownlint MD010 报错;在包含
useState、setOpen、Pressable、View、Text 的组件示例(the JSX block shown)中把所有 Tab
缩进替换为空格缩进(建议 2 或 4 个空格与项目风格一致),确保代码块内每一行的开头没有制表符字符并保存文件后再次运行 lint 验证。
In @.agents/skills/vercel-react-native-skills/rules/ui-styling.md:
- Around line 19-23: The file contains hard tab characters triggering
markdownlint MD010 (e.g., within the code block showing "{ borderRadius: 12,
borderCurve: 'continuous' }" and the following "Use `gap` instead of margin for
spacing between elements:" lines and the region noted also applies to lines
32-39); replace all hard tabs with spaces in those sections so the code block,
headings, and list content use spaces consistently (convert any '\t' to
appropriate number of spaces) and re-run markdownlint to confirm MD010 is
resolved.
In `@src/hooks/stores/usePlayerStore.ts`:
- Around line 32-57: The sync() function can suffer a race where an earlier
getTrackByUniqueKey result overwrites a newer track; after awaiting
trackService.getTrackByUniqueKey(currentTrack.id) (and before calling set({
internalTrack: ... }) or set({ internalTrack: null })), re-read the current
store orpheusTrack?.id (via get()) and compare it to the original newTrackId;
only apply the set if they still match. Apply the same check both on success
(set internalTrack) and on error (set internalTrack to null / toast) so stale
async responses do not mutate state for a newer track.
🧹 Nitpick comments (22)
.agents/skills/vercel-react-native-skills/rules/ui-safe-area-scroll.md (1)
1-65: iOS 安全区域处理文档准确,但可考虑补充跨平台说明。文档正确地推荐在 iOS 上使用
contentInsetAdjustmentBehavior="automatic"来处理安全区域。这种原生方法确实能更好地处理动态安全区域(键盘、工具栏)。不过需要注意:
contentInsetAdjustmentBehavior是 iOS 专属属性,在 Android 上无效。如果这份文档面向跨平台开发,可以考虑添加关于 Android 平台处理方式的说明。.agents/skills/react-native-best-practices/references/native-threading-model.md (1)
124-165: 替换硬制表符为空格以保持一致性。markdownlint 工具检测到多处使用了硬制表符(hard tabs)。为了保持 Markdown 文件的一致性和跨编辑器的可读性,建议将所有硬制表符替换为空格。
🔧 修复建议
在整个文件中,将代码块和表格中的制表符替换为空格(通常使用 2 或 4 个空格)。可以使用编辑器的"将制表符转换为空格"功能批量处理。
.agents/skills/vercel-react-native-skills/rules/ui-pressable.md (1)
21-64: 替换代码块中的硬制表符。代码示例中检测到硬制表符。建议将所有制表符替换为空格(通常使用制表符宽度对应的空格数),以保持代码格式的一致性。
.agents/skills/vercel-react-native-skills/rules/react-compiler-reanimated-shared-values.md (1)
20-52: 将代码示例中的制表符替换为空格。代码块中使用了硬制表符。为了保持代码格式的一致性,建议将制表符转换为空格。
.agents/skills/vercel-react-native-skills/rules/scroll-position-no-state.md (1)
18-61: 代码块中存在硬制表符。多个代码示例中使用了制表符进行缩进。建议统一使用空格以保持格式一致性。
.agents/skills/vercel-react-native-skills/rules/list-performance-item-expensive.md (1)
1-98: 建议修复代码块中的制表符格式问题。文档内容优秀,准确展示了列表项性能优化的最佳实践:
- 正确识别了在列表项中进行数据查询、多次访问 Context 和昂贵计算的问题
- Zustand 选择器示例很好地展示了替代 Context 的方案
- 使用
Set.has()而非Array.includes()是很好的性能建议但代码块中使用了硬制表符(hard tabs),在 Markdown 中应使用空格以保持一致性。
♻️ 建议将代码块中的制表符替换为空格
静态分析工具标记了以下行中的硬制表符:
- Lines 18-28, 30 (第一个代码块)
- Lines 38-45 (第二个代码块)
- Lines 54-67 (第三个代码块)
- Lines 76-78, 83-85 (最后两个代码块)
建议将所有代码块中的制表符替换为空格(通常使用 2 或 4 个空格缩进)。
.agents/skills/vercel-react-native-skills/rules/ui-native-modals.md (1)
1-86: 文档内容准确,但存在格式问题。这份关于原生模态框的指导很有价值:
- 正确推荐使用原生
Modal组件而非 JS 底部弹出层库presentationStyle='formSheet'的使用正确- React Navigation v7 的
sheetAllowedDetents配置准确- 强调原生手势、无障碍功能和性能优势的观点合理
但代码块中存在硬制表符格式问题,建议替换为空格以保持 Markdown 一致性(影响行:21-38, 48-67, 76-81)。
.agents/skills/react-native-best-practices/references/js-measure-fps.md (2)
76-82: 代码块缺少语言标识符。Line 76 的围栏代码块应该指定语言标识符以提高可读性和语法高亮。由于这是标记列表的文本输出,建议使用
text或plaintext。♻️ 建议的修复
-``` +```text 1. Native Process Init (nativeLaunchStart → nativeLaunchEnd) 2. Native App Init (appCreationStart → appCreationEnd)
151-157: 代码示例准确,但存在格式问题。阻塞循环示例正确展示了如何导致丢帧问题,frame budget 的计算也准确:
- 60 FPS = 16.6ms
- 120 FPS = 8.3ms
但代码块中使用了硬制表符(lines 152-156),建议替换为空格。
.agents/skills/react-native-best-practices/references/native-measure-tti.md (3)
76-82: 代码块缺少语言标识符。Line 76 的围栏代码块应该指定语言标识符。建议使用
text以提高可读性。
90-117: 原生代码示例准确。iOS 和 Android 的冷启动检测实现都正确:
- Swift 中使用
ProcessInfo.processInfo.environment["ActivePrewarm"]检测预热启动- Kotlin 中使用
Handler().post和ActivityLifecycleCallbacks检测冷启动- 逻辑清晰,实现可靠
但代码块中存在硬制表符格式问题(建议使用空格)。
176-204: JavaScript 性能标记实现正确。代码示例准确展示了:
- 使用
performance.mark('screenInteractive')标记交互时机- 使用
performance.getEntriesByType('mark')收集指标- 正确计算各阶段的持续时间
但存在硬制表符格式问题(lines 177-180, 182, 192-203),建议替换为空格。
.agents/skills/vercel-react-native-skills/rules/list-performance-images.md (1)
1-53: 图片优化指导准确且实用。这份文档正确展示了列表中图片优化的最佳实践:
- 清晰对比了加载全分辨率图片(4000x3000)与缩略图(200x200)的区别
- URL 查询参数
?w=200&h=200&fit=cover是常见的 CDN 图片调整模式- 推荐在 Retina 屏幕上使用 2x 尺寸(显示 100x100,请求 200x200)是正确的
contentFit='cover'是expo-image的正确属性- 推荐使用
expo-image或SolitoImage以获得缓存和占位符支持但代码块中存在硬制表符格式问题(lines 21-47),建议替换为空格以保持一致性。
.agents/skills/vercel-react-native-skills/rules/react-state-dispatcher.md (1)
21-25: 考虑使用空格代替硬制表符以保持格式一致性。代码块中使用了硬制表符进行缩进。虽然这不会影响文档功能,但使用空格(通常是2或4个)可以提高跨不同编辑器和查看器的一致性。
Also applies to: 35-39, 54-55, 65-66, 79-79, 89-89
.agents/skills/vercel-react-native-skills/rules/animation-gpu-properties.md (1)
20-22: 考虑使用空格代替硬制表符以保持格式一致性。与其他文档文件类似,代码块中使用了硬制表符。为了在整个文档集中保持一致性,建议使用空格进行缩进。
Also applies to: 26-43, 51-60, 62-63
.agents/skills/react-native-best-practices/references/bundle-library-size.md (1)
52-60: 考虑为代码块添加语言标识符。某些代码块缺少语言标识符(例如
bash、text或plaintext),这可能会影响语法高亮显示。添加适当的语言标识符可以提高可读性。♻️ 建议的改进
例如,对于 URL 示例:
-``` +```text https://bundlephobia.com/package/[package-name]对于大小比较示例: ```diff -``` +```text moment (289 kB) vs date-fns (75 kB) vs dayjs (6 kB)</details> Also applies to: 103-105, 109-111 </blockquote></details> <details> <summary>.agents/skills/vercel-react-native-skills/rules/list-performance-virtualize.md (1)</summary><blockquote> `19-28`: **考虑使用空格代替硬制表符以保持格式一致性。** 代码块中的硬制表符缩进与项目中其他文档文件的模式一致。为了提高一致性,可以考虑统一使用空格。 Also applies to: 39-47, 58-65 </blockquote></details> <details> <summary>src/app/(tabs)/library/[tab].tsx (1)</summary><blockquote> `8-97`: **使用 `startTransition` 包裹 Tab 切换更新是最佳实践。** 可降低高频状态更新对主线程的影响,提升切换流畅度。建议进一步利用 `useTransition` 返回的 `isPending` 状态为用户提供视觉反馈(如高亮待切换的 Tab 或显示加载指示器),以进一步优化用户体验。 </blockquote></details> <details> <summary>src/hooks/player/useCurrentTrack.ts (1)</summary><blockquote> `5-5`: **`useShallow` 对于单值选择器是不必要的。** `useShallow` 用于浅比较多个选择值(如解构对象),以避免不必要的重新渲染。对于选择单个值(如 `state.internalTrack`),直接使用普通选择器即可,`useShallow` 只会增加额外开销。 <details> <summary>♻️ 建议的修改</summary> ```diff -import { useShallow } from 'zustand/react/shallow' - export function useCurrentTrack() { - return usePlayerStore(useShallow((state) => state.internalTrack)) + return usePlayerStore((state) => state.internalTrack) }src/hooks/player/useIsCurrentTrack.ts (1)
5-7:useShallow对于返回布尔值的选择器是不必要的。选择器返回的是原始布尔值 (
state.orpheusTrack?.id === trackUniqueKey)。Zustand 默认使用Object.is进行相等性比较,对于原始类型(如 boolean、string、number)已经足够高效。useShallow主要用于浅比较对象/数组,在这里没有实际作用。♻️ 建议的修改
-import { useShallow } from 'zustand/react/shallow' - export function useIsCurrentTrack(trackUniqueKey: string) { - return usePlayerStore( - useShallow((state) => state.orpheusTrack?.id === trackUniqueKey), - ) + return usePlayerStore((state) => state.orpheusTrack?.id === trackUniqueKey) }.agents/skills/react-native-best-practices/references/js-atomic-state.md (1)
15-237: 建议:将代码块中的硬制表符替换为空格文档的代码示例中使用了硬制表符(hard tabs)进行缩进。为保持与 Markdown 最佳实践的一致性,建议将所有代码块中的制表符替换为空格(通常使用 2 或 4 个空格)。
这样可以确保代码在不同编辑器和查看器中显示一致。
📝 修复建议
可以使用以下命令批量替换:
# 将制表符替换为 2 个空格 sed -i 's/\t/ /g' .agents/skills/react-native-best-practices/references/js-atomic-state.md或在代码编辑器中使用"将制表符转换为空格"功能。
基于代码规范:markdownlint 规则 MD010 建议在 Markdown 文件中使用空格而非硬制表符。
.agents/skills/react-native-best-practices/references/bundle-analyze-app.md (1)
130-135: 建议:为代码块指定语言标识符第 130 行的代码块缺少语言标识符。这是一个示例输出文本,建议添加
text或plaintext标识符以提高文档的清晰度。📝 修复建议
-``` +```text Variant: SampleApp-<UUID>.ipa App + On Demand Resources size: 3.5 MB compressed, 10.6 MB uncompressed App size: 3.5 MB compressed, 10.6 MB uncompressed</details> 基于代码规范:markdownlint 规则 MD040 要求为所有代码块指定语言。 </blockquote></details> </blockquote></details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
| ```javascript | ||
| // rspack.config.js | ||
| const { RsdoctorRspackPlugin } = require('@rsdoctor/rspack-plugin') | ||
|
|
||
| module.exports = { | ||
| plugins: [process.env.RSDOCTOR && new RsdoctorRspackPlugin()].filter(Boolean), | ||
| } | ||
| ``` |
There was a problem hiding this comment.
将制表符替换为空格以保持一致性
JavaScript 代码示例中使用了硬制表符(hard tabs)进行缩进,这违反了 Markdown 格式规范。建议使用空格代替制表符以保持文档格式的一致性。
🔧 建议的修复
```javascript
// rspack.config.js
const { RsdoctorRspackPlugin } = require('@rsdoctor/rspack-plugin')
module.exports = {
- plugins: [process.env.RSDOCTOR && new RsdoctorRspackPlugin()].filter(Boolean),
+ plugins: [process.env.RSDOCTOR && new RsdoctorRspackPlugin()].filter(Boolean),
}
</details>
基于静态分析工具 markdownlint-cli2 的提示。
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>
160-160: Hard tabs
Column: 1
(MD010, no-hard-tabs)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
In @.agents/skills/react-native-best-practices/references/bundle-analyze-js.md
around lines 155 - 162, The snippet in rspack.config.js uses hard tabs for
indentation; replace tabs with spaces in the JavaScript code block so formatting
is consistent with Markdown lint rules — update the lines containing
RsdoctorRspackPlugin, the plugins array and the process.env.RSDOCTOR expression
to use spaces instead of tabs (e.g., two or two/consistent spaces) across the
code block.
</details>
<!-- fingerprinting:phantom:triton:puma -->
<!-- This is an auto-generated comment by CodeRabbit -->
| ``` | ||
| Warning: Require cycle: | ||
| components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts | ||
| ``` |
There was a problem hiding this comment.
为代码块补充语言标识以满足 MD040。
Line 77 的 fenced code block 没有语言标识,markdownlint 会报错。建议补上(如 text 或 tsx)。
🛠️ 建议修复
-```
+```text
Warning: Require cycle:
components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **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.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
77-77: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In
@.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md
around lines 77 - 80, The fenced code block that currently contains the Require
cycle warning (the block starting with "Warning: Require cycle:
components/index.ts -> Button.tsx -> utils/index.ts -> components/index.ts") is
missing a language tag; update that code fence to include a language identifier
(for example `text` or `tsx`) so MarkdownLint rule MD040 is satisfied — locate
the fenced block and change the opening backticks from ``` to ```text (or
```tsx) accordingly.
| export default [ | ||
| { | ||
| plugins: { 'no-barrel-files': noBarrelFiles }, | ||
| rules: { | ||
| 'no-barrel-files/no-barrel-files': 'error', | ||
| }, | ||
| }, |
There was a problem hiding this comment.
将代码块中的 Tab 替换为空格以通过 MD010。
Line 108-113 使用了硬 Tab,markdownlint 会报错;建议统一为空格缩进。
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
108-108: Hard tabs
Column: 1
(MD010, no-hard-tabs)
109-109: Hard tabs
Column: 1
(MD010, no-hard-tabs)
110-110: Hard tabs
Column: 1
(MD010, no-hard-tabs)
111-111: Hard tabs
Column: 1
(MD010, no-hard-tabs)
112-112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
113-113: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In
@.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md
around lines 107 - 113, The code block containing the export default array
(starts with "export default [" and includes the plugins/rules object and
'no-barrel-files/no-barrel-files') uses hard tabs for indentation which violates
MD010; open that code block and replace each tab character with spaces (use the
repository's markdown indentation style, e.g., 2 or 4 spaces consistently) so
the lines for plugins, rules, and the rule entry are space-indented instead of
tab-indented.
| ``` | ||
| assets/ | ||
| ├── image.jpg # 1x resolution (base) | ||
| ├── image@2x.jpg # 2x resolution | ||
| └── image@3x.jpg # 3x resolution | ||
| ``` |
There was a problem hiding this comment.
为未标注语言的代码围栏补充语言标识以通过 lint。
markdownlint 报告 MD040。建议为纯文本输出统一标注 text(或 plaintext),避免渲染与 lint 失败。
🛠️ 建议修改
-```
+```text
assets/
├── image.jpg # 1x resolution (base)
├── image@2x.jpg # 2x resolution
└── image@3x.jpg # 3x resolution
-```
+```
-```
+```text
android/app/build/outputs/bundle/release/
└── base/
└── res/
├── drawable-mdpi-v4/ # 1x
├── drawable-hdpi-v4/ # 1.5x
├── drawable-xhdpi-v4/ # 2x
├── drawable-xxhdpi-v4/ # 3x
└── drawable-xxxhdpi-v4/ # 4x
-```
+```
-```
+```text
ios/RNAssets.xcassets/
-```
+```
-```
+```text
ios/RNAssets.xcassets/
└── assets_image_image.imageset/
├── Contents.json
├── image.jpg
├── image@2x.jpg
└── image@3x.jpg
-```
+```
-```
+```text
App bundle contains:
├── image.jpg (100 KB)
├── image@2x.jpg (300 KB)
└── image@3x.jpg (600 KB)
Total: 1 MB
-```
+```
-```
+```text
iPhone 15 Pro receives:
└── image@3x.jpg (600 KB)
Total: 600 KB (40% smaller)
-```
+```
-```
+```text
Variant: MyApp-<UUID>.ipa
Supported variant descriptors: iPhone15,2 ...
App size: 3.5 MB compressed, 10.6 MB uncompressed
-```
+```Also applies to: 59-68, 82-84, 125-132, 140-146, 150-154, 193-197
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
33-33: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In
@.agents/skills/react-native-best-practices/references/bundle-native-assets.md
around lines 33 - 38, The markdown contains multiple fenced code blocks without
a language tag (e.g., the blocks starting with "assets/",
"android/app/build/outputs/bundle/release/", "ios/RNAssets.xcassets/", "App
bundle contains:", "iPhone 15 Pro receives:", and "Variant: MyApp-<UUID>.ipa");
update each of these backtick-fenced blocks to use a language identifier of
"text" (i.e., replace ``` with ```text) so markdownlint MD040 is satisfied and
rendering/linting is consistent across the document.
| ### Library Specific Rules | ||
|
|
||
| Many libraries provide ProGuard rules. Check: |
There was a problem hiding this comment.
小幅语法修正:建议使用连字符。
“Library Specific Rules” 建议改为 “Library-specific Rules”。
🧰 Tools
🪛 LanguageTool
[grammar] ~168-~168: Use a hyphen to join words.
Context: ... ``` 3. Rebuild and test ### Library Specific Rules Many libraries provide P...
(QB_NEW_EN_HYPHEN)
🤖 Prompt for AI Agents
In @.agents/skills/react-native-best-practices/references/bundle-r8-android.md
around lines 168 - 170, Update the header text "### Library Specific Rules" to
use a hyphenated form "### Library-specific Rules" to correct the grammar;
locate the header string in the markdown (the line containing "Library Specific
Rules") and replace it with the hyphenated version.
| function App() { | ||
| return ( | ||
| <Stack.Navigator> | ||
| <Stack.Screen | ||
| name='Home' | ||
| component={HomeScreen} | ||
| /> | ||
| <Stack.Screen | ||
| name='Details' | ||
| component={DetailsScreen} | ||
| /> | ||
| </Stack.Navigator> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| **Correct (native stack with react-navigation):** | ||
|
|
||
| ```tsx | ||
| import { createNativeStackNavigator } from '@react-navigation/native-stack' | ||
|
|
||
| const Stack = createNativeStackNavigator() | ||
|
|
||
| function App() { | ||
| return ( | ||
| <Stack.Navigator> | ||
| <Stack.Screen | ||
| name='Home' | ||
| component={HomeScreen} | ||
| /> | ||
| <Stack.Screen | ||
| name='Details' | ||
| component={DetailsScreen} | ||
| /> | ||
| </Stack.Navigator> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| **Correct (expo-router uses native stack by default):** | ||
|
|
||
| ```tsx | ||
| // app/_layout.tsx | ||
| import { Stack } from 'expo-router' | ||
|
|
||
| export default function Layout() { | ||
| return <Stack /> | ||
| } | ||
| ``` | ||
|
|
||
| ### Tab Navigation | ||
|
|
||
| **Incorrect (JS bottom tabs):** | ||
|
|
||
| ```tsx | ||
| import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' | ||
|
|
||
| const Tab = createBottomTabNavigator() | ||
|
|
||
| function App() { | ||
| return ( | ||
| <Tab.Navigator> | ||
| <Tab.Screen | ||
| name='Home' | ||
| component={HomeScreen} | ||
| /> | ||
| <Tab.Screen | ||
| name='Settings' | ||
| component={SettingsScreen} | ||
| /> | ||
| </Tab.Navigator> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| **Correct (native bottom tabs with react-navigation):** | ||
|
|
||
| ```tsx | ||
| import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation' | ||
|
|
||
| const Tab = createNativeBottomTabNavigator() | ||
|
|
||
| function App() { | ||
| return ( | ||
| <Tab.Navigator> | ||
| <Tab.Screen | ||
| name='Home' | ||
| component={HomeScreen} | ||
| options={{ | ||
| tabBarIcon: () => ({ sfSymbol: 'house' }), | ||
| }} | ||
| /> | ||
| <Tab.Screen | ||
| name='Settings' | ||
| component={SettingsScreen} | ||
| options={{ | ||
| tabBarIcon: () => ({ sfSymbol: 'gear' }), | ||
| }} | ||
| /> | ||
| </Tab.Navigator> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| **Correct (expo-router native tabs):** | ||
|
|
||
| ```tsx | ||
| // app/(tabs)/_layout.tsx | ||
| import { NativeTabs } from 'expo-router/unstable-native-tabs' | ||
|
|
||
| export default function TabLayout() { | ||
| return ( | ||
| <NativeTabs> | ||
| <NativeTabs.Trigger name='index'> | ||
| <NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label> | ||
| <NativeTabs.Trigger.Icon | ||
| sf='house.fill' | ||
| md='home' | ||
| /> | ||
| </NativeTabs.Trigger> | ||
| <NativeTabs.Trigger name='settings'> | ||
| <NativeTabs.Trigger.Label>Settings</NativeTabs.Trigger.Label> | ||
| <NativeTabs.Trigger.Icon | ||
| sf='gear' | ||
| md='settings' | ||
| /> | ||
| </NativeTabs.Trigger> | ||
| </NativeTabs> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| On iOS, native tabs automatically enable `contentInsetAdjustmentBehavior` on the | ||
| first `ScrollView` at the root of each tab screen, so content scrolls correctly | ||
| behind the translucent tab bar. If you need to disable this, use | ||
| `disableAutomaticContentInsets` on the trigger. | ||
|
|
||
| ### Prefer Native Header Options Over Custom Components | ||
|
|
||
| **Incorrect (custom header component):** | ||
|
|
||
| ```tsx | ||
| <Stack.Screen | ||
| name='Profile' | ||
| component={ProfileScreen} | ||
| options={{ | ||
| header: () => <CustomHeader title='Profile' />, | ||
| }} | ||
| /> | ||
| ``` | ||
|
|
||
| **Correct (native header options):** | ||
|
|
||
| ```tsx | ||
| <Stack.Screen | ||
| name='Profile' | ||
| component={ProfileScreen} | ||
| options={{ | ||
| title: 'Profile', | ||
| headerLargeTitleEnabled: true, | ||
| headerSearchBarOptions: { | ||
| placeholder: 'Search', | ||
| }, | ||
| }} | ||
| /> |
There was a problem hiding this comment.
将示例代码中的硬 Tab 替换为空格以通过 markdownlint。
MD010 报告了多处硬 Tab;建议在所有代码块内统一用空格缩进。
🛠️ 示例修正(其余代码块同样处理)
-function App() {
- return (
- <Stack.Navigator>
- <Stack.Screen
- name='Home'
- component={HomeScreen}
- />
- <Stack.Screen
- name='Details'
- component={DetailsScreen}
- />
- </Stack.Navigator>
- )
-}
+function App() {
+ return (
+ <Stack.Navigator>
+ <Stack.Screen
+ name='Home'
+ component={HomeScreen}
+ />
+ <Stack.Screen
+ name='Details'
+ component={DetailsScreen}
+ />
+ </Stack.Navigator>
+ )
+}🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
30-30: Hard tabs
Column: 1
(MD010, no-hard-tabs)
31-31: Hard tabs
Column: 1
(MD010, no-hard-tabs)
32-32: Hard tabs
Column: 1
(MD010, no-hard-tabs)
33-33: Hard tabs
Column: 1
(MD010, no-hard-tabs)
34-34: Hard tabs
Column: 1
(MD010, no-hard-tabs)
35-35: Hard tabs
Column: 1
(MD010, no-hard-tabs)
36-36: Hard tabs
Column: 1
(MD010, no-hard-tabs)
37-37: Hard tabs
Column: 1
(MD010, no-hard-tabs)
38-38: Hard tabs
Column: 1
(MD010, no-hard-tabs)
39-39: Hard tabs
Column: 1
(MD010, no-hard-tabs)
40-40: Hard tabs
Column: 1
(MD010, no-hard-tabs)
41-41: Hard tabs
Column: 1
(MD010, no-hard-tabs)
53-53: Hard tabs
Column: 1
(MD010, no-hard-tabs)
54-54: Hard tabs
Column: 1
(MD010, no-hard-tabs)
55-55: Hard tabs
Column: 1
(MD010, no-hard-tabs)
56-56: Hard tabs
Column: 1
(MD010, no-hard-tabs)
57-57: Hard tabs
Column: 1
(MD010, no-hard-tabs)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
60-60: Hard tabs
Column: 1
(MD010, no-hard-tabs)
61-61: Hard tabs
Column: 1
(MD010, no-hard-tabs)
62-62: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Hard tabs
Column: 1
(MD010, no-hard-tabs)
64-64: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Hard tabs
Column: 1
(MD010, no-hard-tabs)
89-89: Hard tabs
Column: 1
(MD010, no-hard-tabs)
90-90: Hard tabs
Column: 1
(MD010, no-hard-tabs)
91-91: Hard tabs
Column: 1
(MD010, no-hard-tabs)
92-92: Hard tabs
Column: 1
(MD010, no-hard-tabs)
93-93: Hard tabs
Column: 1
(MD010, no-hard-tabs)
94-94: Hard tabs
Column: 1
(MD010, no-hard-tabs)
95-95: Hard tabs
Column: 1
(MD010, no-hard-tabs)
96-96: Hard tabs
Column: 1
(MD010, no-hard-tabs)
97-97: Hard tabs
Column: 1
(MD010, no-hard-tabs)
98-98: Hard tabs
Column: 1
(MD010, no-hard-tabs)
99-99: Hard tabs
Column: 1
(MD010, no-hard-tabs)
100-100: Hard tabs
Column: 1
(MD010, no-hard-tabs)
112-112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
113-113: Hard tabs
Column: 1
(MD010, no-hard-tabs)
114-114: Hard tabs
Column: 1
(MD010, no-hard-tabs)
115-115: Hard tabs
Column: 1
(MD010, no-hard-tabs)
116-116: Hard tabs
Column: 1
(MD010, no-hard-tabs)
117-117: Hard tabs
Column: 1
(MD010, no-hard-tabs)
118-118: Hard tabs
Column: 1
(MD010, no-hard-tabs)
119-119: Hard tabs
Column: 1
(MD010, no-hard-tabs)
120-120: Hard tabs
Column: 1
(MD010, no-hard-tabs)
121-121: Hard tabs
Column: 1
(MD010, no-hard-tabs)
122-122: Hard tabs
Column: 1
(MD010, no-hard-tabs)
123-123: Hard tabs
Column: 1
(MD010, no-hard-tabs)
124-124: Hard tabs
Column: 1
(MD010, no-hard-tabs)
125-125: Hard tabs
Column: 1
(MD010, no-hard-tabs)
126-126: Hard tabs
Column: 1
(MD010, no-hard-tabs)
127-127: Hard tabs
Column: 1
(MD010, no-hard-tabs)
128-128: Hard tabs
Column: 1
(MD010, no-hard-tabs)
129-129: Hard tabs
Column: 1
(MD010, no-hard-tabs)
140-140: Hard tabs
Column: 1
(MD010, no-hard-tabs)
141-141: Hard tabs
Column: 1
(MD010, no-hard-tabs)
142-142: Hard tabs
Column: 1
(MD010, no-hard-tabs)
143-143: Hard tabs
Column: 1
(MD010, no-hard-tabs)
144-144: Hard tabs
Column: 1
(MD010, no-hard-tabs)
145-145: Hard tabs
Column: 1
(MD010, no-hard-tabs)
146-146: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
148-148: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
151-151: Hard tabs
Column: 1
(MD010, no-hard-tabs)
152-152: Hard tabs
Column: 1
(MD010, no-hard-tabs)
153-153: Hard tabs
Column: 1
(MD010, no-hard-tabs)
154-154: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
156-156: Hard tabs
Column: 1
(MD010, no-hard-tabs)
157-157: Hard tabs
Column: 1
(MD010, no-hard-tabs)
172-172: Hard tabs
Column: 1
(MD010, no-hard-tabs)
173-173: Hard tabs
Column: 1
(MD010, no-hard-tabs)
174-174: Hard tabs
Column: 1
(MD010, no-hard-tabs)
175-175: Hard tabs
Column: 1
(MD010, no-hard-tabs)
176-176: Hard tabs
Column: 1
(MD010, no-hard-tabs)
184-184: Hard tabs
Column: 1
(MD010, no-hard-tabs)
185-185: Hard tabs
Column: 1
(MD010, no-hard-tabs)
186-186: Hard tabs
Column: 1
(MD010, no-hard-tabs)
187-187: Hard tabs
Column: 1
(MD010, no-hard-tabs)
188-188: Hard tabs
Column: 1
(MD010, no-hard-tabs)
189-189: Hard tabs
Column: 1
(MD010, no-hard-tabs)
190-190: Hard tabs
Column: 1
(MD010, no-hard-tabs)
191-191: Hard tabs
Column: 1
(MD010, no-hard-tabs)
192-192: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In
@.agents/skills/vercel-react-native-skills/rules/navigation-native-navigators.md
around lines 29 - 193, 文件中的多个 Markdown 代码块使用了硬 Tab 导致 MD010
报告;在包含示例的代码块(例如函数/组件名 App、Layout、TabLayout、以及 JSX 片段含
Stack.Navigator、Tab.Navigator、Stack.Screen、NativeTabs.Trigger 等)中将所有硬制 Tab
字符替换为一致的空格缩进(例如 2 个或 4 个空格),对所有代码块执行相同替换并保存,然后重新运行 markdownlint/MD010 验证修复。
| const ref = useRef<View>(null) | ||
| const [height, setHeight] = useState<number | undefined>(undefined) | ||
|
|
||
| useLayoutEffect(() => { | ||
| // Sync measurement on mount (RN 0.82+) | ||
| const rect = ref.current?.getBoundingClientRect() | ||
| if (rect) setHeight(rect.height) | ||
| // Pre-0.82: ref.current?.measure((x, y, w, h) => setHeight(h)) | ||
| }, []) | ||
|
|
||
| const onLayout = (e: LayoutChangeEvent) => { | ||
| setHeight(e.nativeEvent.layout.height) | ||
| } | ||
|
|
||
| return ( | ||
| <View | ||
| ref={ref} | ||
| onLayout={onLayout} | ||
| > | ||
| {children} | ||
| </View> | ||
| ) |
There was a problem hiding this comment.
代码块内请避免硬 Tab(MD010)。
Line 22-43 使用 Tab 缩进,markdownlint 会报错;建议统一替换为空格。
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
22-22: Hard tabs
Column: 1
(MD010, no-hard-tabs)
23-23: Hard tabs
Column: 1
(MD010, no-hard-tabs)
25-25: Hard tabs
Column: 1
(MD010, no-hard-tabs)
26-26: Hard tabs
Column: 1
(MD010, no-hard-tabs)
27-27: Hard tabs
Column: 1
(MD010, no-hard-tabs)
28-28: Hard tabs
Column: 1
(MD010, no-hard-tabs)
29-29: Hard tabs
Column: 1
(MD010, no-hard-tabs)
30-30: Hard tabs
Column: 1
(MD010, no-hard-tabs)
32-32: Hard tabs
Column: 1
(MD010, no-hard-tabs)
33-33: Hard tabs
Column: 1
(MD010, no-hard-tabs)
34-34: Hard tabs
Column: 1
(MD010, no-hard-tabs)
36-36: Hard tabs
Column: 1
(MD010, no-hard-tabs)
37-37: Hard tabs
Column: 1
(MD010, no-hard-tabs)
38-38: Hard tabs
Column: 1
(MD010, no-hard-tabs)
39-39: Hard tabs
Column: 1
(MD010, no-hard-tabs)
40-40: Hard tabs
Column: 1
(MD010, no-hard-tabs)
41-41: Hard tabs
Column: 1
(MD010, no-hard-tabs)
42-42: Hard tabs
Column: 1
(MD010, no-hard-tabs)
43-43: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In @.agents/skills/vercel-react-native-skills/rules/ui-measure-views.md around
lines 22 - 43, 代码块第22-43行使用硬Tab导致 markdownlint MD010 报错;请在该代码片段中将所有硬 Tab
替换为空格(建议每级缩进用两个或四个空格),检查并修复涉及到 useRef<View>(null), useLayoutEffect, onLayout 和
LayoutChangeEvent 的缩进以保持一致性,确保返回的 JSX <View ref={ref} onLayout={onLayout}>
区块及内部子节点也使用空格缩进以通过 lint 校验。
| const [open, setOpen] = useState(false) | ||
|
|
||
| return ( | ||
| <View> | ||
| <Pressable onPress={() => setOpen(!open)}> | ||
| <Text>Open Menu</Text> | ||
| </Pressable> | ||
| {open && ( | ||
| <View style={{ position: 'absolute', top: 40 }}> | ||
| <Pressable onPress={() => console.log('edit')}> | ||
| <Text>Edit</Text> | ||
| </Pressable> | ||
| <Pressable onPress={() => console.log('delete')}> | ||
| <Text>Delete</Text> | ||
| </Pressable> | ||
| </View> | ||
| )} | ||
| </View> | ||
| ) |
There was a problem hiding this comment.
代码块内请避免硬 Tab(MD010)。
Line 21-39 使用 Tab 缩进,markdownlint 会报错;建议统一替换为空格。
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
21-21: Hard tabs
Column: 1
(MD010, no-hard-tabs)
23-23: Hard tabs
Column: 1
(MD010, no-hard-tabs)
24-24: Hard tabs
Column: 1
(MD010, no-hard-tabs)
25-25: Hard tabs
Column: 1
(MD010, no-hard-tabs)
26-26: Hard tabs
Column: 1
(MD010, no-hard-tabs)
27-27: Hard tabs
Column: 1
(MD010, no-hard-tabs)
28-28: Hard tabs
Column: 1
(MD010, no-hard-tabs)
29-29: Hard tabs
Column: 1
(MD010, no-hard-tabs)
30-30: Hard tabs
Column: 1
(MD010, no-hard-tabs)
31-31: Hard tabs
Column: 1
(MD010, no-hard-tabs)
32-32: Hard tabs
Column: 1
(MD010, no-hard-tabs)
33-33: Hard tabs
Column: 1
(MD010, no-hard-tabs)
34-34: Hard tabs
Column: 1
(MD010, no-hard-tabs)
35-35: Hard tabs
Column: 1
(MD010, no-hard-tabs)
36-36: Hard tabs
Column: 1
(MD010, no-hard-tabs)
37-37: Hard tabs
Column: 1
(MD010, no-hard-tabs)
38-38: Hard tabs
Column: 1
(MD010, no-hard-tabs)
39-39: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In @.agents/skills/vercel-react-native-skills/rules/ui-menus.md around lines 21
- 39, 代码块中使用了硬 Tab 导致 markdownlint MD010 报错;在包含
useState、setOpen、Pressable、View、Text 的组件示例(the JSX block shown)中把所有 Tab
缩进替换为空格缩进(建议 2 或 4 个空格与项目风格一致),确保代码块内每一行的开头没有制表符字符并保存文件后再次运行 lint 验证。
| { borderRadius: 12, borderCurve: 'continuous' } | ||
| ``` | ||
|
|
||
| **Use `gap` instead of margin for spacing between elements:** | ||
|
|
There was a problem hiding this comment.
请移除硬制表符(MD010)
这些行含硬 tabs,建议统一改为空格,避免 markdownlint 报错。
✅ 示例修正
- <Text>First</Text>
- <Text>Second</Text>
+ <Text>First</Text>
+ <Text>Second</Text>Also applies to: 32-39
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
19-19: Hard tabs
Column: 1
(MD010, no-hard-tabs)
20-20: Hard tabs
Column: 1
(MD010, no-hard-tabs)
21-21: Hard tabs
Column: 1
(MD010, no-hard-tabs)
22-22: Hard tabs
Column: 1
(MD010, no-hard-tabs)
23-23: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In @.agents/skills/vercel-react-native-skills/rules/ui-styling.md around lines
19 - 23, The file contains hard tab characters triggering markdownlint MD010
(e.g., within the code block showing "{ borderRadius: 12, borderCurve:
'continuous' }" and the following "Use `gap` instead of margin for spacing
between elements:" lines and the region noted also applies to lines 32-39);
replace all hard tabs with spaces in those sections so the code block, headings,
and list content use spaces consistently (convert any '\t' to appropriate number
of spaces) and re-run markdownlint to confirm MD010 is resolved.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@package.json`:
- Line 98: This dependency "react-native-keyboard-controller" is native and
requires a dev client build and proper synchronized deps: install both
react-native-keyboard-controller and react-native-reanimated, ensure you wrap
your app root with KeyboardProvider in your entry component (e.g., App.tsx),
then rebuild using the Expo dev client (Expo Go won't work); if you hit Android
Kotlin version conflicts, add expo-build-properties configuration in app.json to
set the Kotlin/Gradle versions to match the native modules.
| "react-native-fast-shimmer": "^1.3.4", | ||
| "react-native-gesture-handler": "~2.30.0", | ||
| "react-native-gradle-plugin": "^0.71.19", | ||
| "react-native-keyboard-controller": "1.20.4", |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
react-native-keyboard-controller Expo installation setup documentation
💡 Result:
react-native-keyboard-controller (Expo) — install & setup
1) Use a development build (not Expo Go)
This library includes native code, so it won’t run in Expo Go; use a dev build / prebuild flow. [2]
2) Install the package
npx expo install react-native-keyboard-controller[1][2]
3) Install/verify peer dependency: react-native-reanimated
Keyboard Controller requires react-native-reanimated. [2][3]
4) Wrap your app with KeyboardProvider
Example (Expo Router root layout):
import { Stack } from 'expo-router';
import { KeyboardProvider } from 'react-native-keyboard-controller';
export default function RootLayout() {
return (
<KeyboardProvider>
<Stack />
</KeyboardProvider>
);
}[2][3]
5) Build & run
After adding native deps, rebuild your dev client (for example via EAS build or local prebuild). [3]
(If needed) Expo managed workflow Android Kotlin version fix
If you hit Android build issues related to Kotlin version, the library docs recommend using expo-build-properties and setting a Kotlin version in app.json/app.config.js. [9]
Sources: Expo SDK docs for Keyboard Controller [1], Expo keyboard-handling guide [2], library installation docs [3], library troubleshooting (Expo managed workflow) [9].
确认 dev client 构建要求并关注同步依赖配置
该库包含原生代码,必须使用 dev client 构建(不支持 Expo Go)。核心集成步骤:(1) 安装 react-native-keyboard-controller 和其同步依赖 react-native-reanimated;(2) 在应用入口处用 KeyboardProvider 包装根组件;(3) 执行 dev client 重新构建。如遇 Android Kotlin 版本冲突,可通过 expo-build-properties 在 app.json 中配置。
🤖 Prompt for AI Agents
In `@package.json` at line 98, This dependency "react-native-keyboard-controller"
is native and requires a dev client build and proper synchronized deps: install
both react-native-keyboard-controller and react-native-reanimated, ensure you
wrap your app root with KeyboardProvider in your entry component (e.g.,
App.tsx), then rebuild using the Expo dev client (Expo Go won't work); if you
hit Android Kotlin version conflicts, add expo-build-properties configuration in
app.json to set the Kotlin/Gradle versions to match the native modules.

Summary by CodeRabbit
发布说明
New Features
Performance
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.