react-doctor/rn-bottom-sheet-prefer-native
Use `<Modal presentationStyle="formSheet">` (RN v7+) for native gesture handling and snap points
- Category: React Native
- Severity: warn
- Source:
oxlint-plugin-react-doctor - Framework: react-native
- Enabled when: framework=react-native and capabilities=react-native
Validation prompt
Use this to decide whether a fired diagnostic is real or a false positive.
Confirm the file imports @gorhom/bottom-sheet, react-native-bottom-sheet, react-native-modal-bottom-sheet, or react-native-raw-bottom-sheet — all run gestures and animation on the JS thread. False positive on projects pinned below React Native 0.76 where the native form-sheet Modal API isn't available yet.
Fix prompt
Use this once validation confirms the diagnostic is real.
Replace with the built-in Modal using presentationStyle="formSheet" plus sheetAllowedDetents (e.g. [0.5, 1]) — gestures, detents, and dismissal run on the OS modal stack instead of the JS thread. Requires RN 0.76+ (iOS first, Android still maturing). See https://reactnative.dev/docs/modal#presentationstyle-ios
Related rules
More React Native rules from the rules reference:
react-doctor/rn-detox-missing-await: Prepend await to the Detox action, waitFor chain, or expect(element(...)) assertion: await element(by.id('submit')).tap()react-doctor/rn-list-callback-per-row: Hoist the handler with useCallback at list scope and pass the row id as a primitive prop, so the row's memo() shallow-compare actually hitsreact-doctor/rn-list-data-mapped: Wrap the projection in `useMemo(() => items.map(...), [items])` so the list's `data` prop has a stable reference across parent rendersreact-doctor/rn-list-missing-estimated-item-size: Add estimatedItemSize so FlashList/LegendList sizes its initial container pool correctly: <FlashList data={items} estimatedItemSize={64} />react-doctor/rn-list-recyclable-without-types: Add `getItemType={item => item.kind}` so FlashList keeps separate recycle pools per item type — heterogeneous rows shouldn't share recycled cells