react-doctor/rn-prefer-expo-image
Use `<Image>` from `expo-image` instead of `react-native` — same prop API, plus disk + memory caching, placeholders, and crossfades
- 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.
The rule fires on any ImportSpecifier whose imported name is Image and whose source is exactly "react-native". It doesn't check whether the imported Image is actually rendered, and it misses namespace imports like import * as RN from "react-native". False positive: a bare-workflow or non-Expo project that can't add expo-image as a dependency.
Fix prompt
Use this once validation confirms the diagnostic is real.
Run npx expo install expo-image and change the import to import { Image } from "expo-image". The API maps cleanly — source, style, and contentFit are drop-in — and you gain disk plus memory caching, blurhash and thumbhash placeholders, and crossfades via the transition prop. See https://docs.expo.dev/versions/latest/sdk/image/
Related rules
More React Native rules from the rules reference:
react-doctor/rn-prefer-pressable: Use `<Pressable>` from react-native (or react-native-gesture-handler) instead of legacy Touchable* componentsreact-doctor/rn-prefer-pressable-over-gesture-detector: Replace tap-only `<GestureDetector>` with `<Pressable>`: <Pressable onPress={onPress}> or createCSSAnimatedComponent(Pressable) for animated press feedbackreact-doctor/rn-prefer-reanimated: Use `import Animated from 'react-native-reanimated'` — animations run on the UI thread instead of the JS threadreact-doctor/rn-pressable-shared-value-mutation: Wrap in <GestureDetector gesture={Gesture.Tap()...}> so the press animation runs on the UI thread instead of bouncing across the JS bridgereact-doctor/rn-scrollview-dynamic-padding: Use `contentInset={{ bottom: dynamicValue }}` — the OS applies it as an offset without reflowing the scroll content