A zero-config React Native wrapper that automatically shows a blur or placeholder while images load, then fades it out smoothly.
npm install @twinedo/react-native-image-placeholder react-native-reanimatedOptional blur support (install one):
npm install @react-native-community/blurnpm install expo-blurimport { Image } from 'react-native';
import { ImagePlaceholder } from '@twinedo/react-native-image-placeholder';
<ImagePlaceholder>
<Image
source={{ uri: 'https://example.com/hero.jpg' }}
style={{ width: 240, height: 160, borderRadius: 12 }}
/>
</ImagePlaceholder>;Children must be a single Image-like element (React Native Image, expo-image, FastImage, or any component that forwards load events).
<ImagePlaceholder
enabled?: boolean // default true
minDelay?: number // default 150
fadeDuration?: number // default 600
overlay?: ReactNode
blurAmount?: number
overlayColor?: string
logoUri?: string | ImageSourcePropType
logoWidth?: number
logoHeight?: number
fallback?: 'auto' | 'delay' | 'none'
style?: ViewStyle
>
{childImage}
</ImagePlaceholder>| Prop | Type | Optional | Default | Description |
|---|---|---|---|---|
| children | ReactElement | false | — | Single Image-like element (Image, expo-image, FastImage, or custom). |
| enabled | boolean | true | true | Toggle the overlay behavior on/off. |
| minDelay | number | true | 150 | Minimum time (ms) the overlay stays visible when using fallback delay. |
| fadeDuration | number | true | 600 | Fade-out duration (ms) for the overlay. |
| overlay | ReactNode | true | — | Custom overlay; overrides blur/placeholder rendering. |
| blurAmount | number | true | — | Blur intensity when BlurView is available. |
| overlayColor | string | true | rgba(0, 0, 0, 0.08) | Tint color for the default placeholder/blur overlay. |
| logoUri | string | ImageSourcePropType | true | — | Centered logo shown during loading. |
| logoWidth | number | true | 56 | Logo width in pixels. |
| logoHeight | number | true | 56 | Logo height in pixels. |
| fallback | 'auto' | 'delay' | 'none' | true | auto | How to behave when lifecycle events are unavailable. |
| style | ViewStyle | true | — | Style applied to the wrapper container. |
Notes:
overlayreplaces the default placeholder/blur entirely.overlayrenders inside an absolute-fill container; useStyleSheet.absoluteFillObjectif you want it to cover the image.blurAmountuses an optional BlurView if installed; otherwise the default placeholder is used.overlayColortints the default placeholder/blur (use a darker rgba to deepen the dim effect).logoUriadds a centered logo on top of the default placeholder/blur. It accepts a remote uri string or a staticrequire()asset.fallbackcontrols the behavior when lifecycle events are unavailable:auto: use load events when available, otherwise fall back to a timed delay.delay: always use the timed delay (useful for custom images that never emit events).none: only use lifecycle events and never fall back.
When fallback is active, the overlay stays visible for at least minDelay and then fades out over fadeDuration. This prevents flashes for cached images and still feels responsive for fast loads.
<ImagePlaceholder blurAmount={12}>
<Image source={{ uri: 'https://example.com/hero.jpg' }} style={{ width: 240, height: 160 }} />
</ImagePlaceholder>If you want full control, pass a custom overlay:
import { StyleSheet } from 'react-native';
import { BlurView } from '@react-native-community/blur';
<ImagePlaceholder
overlay={<BlurView blurAmount={16} style={{ ...StyleSheet.absoluteFillObject }} />}
>
<Image source={{ uri: 'https://example.com/hero.jpg' }} style={{ width: 240, height: 160 }} />
</ImagePlaceholder>const logo = require('./assets/icon.png');
<ImagePlaceholder blurAmount={12} logoUri={logo} logoWidth={64} logoHeight={64}>
<Image source={{ uri: 'https://example.com/hero.jpg' }} style={{ width: 240, height: 160 }} />
</ImagePlaceholder>react-native-reanimatedis required. Ensure the Reanimated Babel plugin is installed and configured.- Bare React Native: after installing native deps, run
pod installin theiosdirectory. - Expo: use
expo-blurfor blur overlays or pass a custom overlay. Expo already configures Reanimated for managed projects.
import { Image } from 'react-native';
import { ImagePlaceholder } from '@twinedo/react-native-image-placeholder';
export function Avatar() {
return (
<ImagePlaceholder fadeDuration={500} minDelay={120} blurAmount={10}>
<Image
source={{ uri: 'https://images.example.com/avatar.png' }}
style={{ width: 80, height: 80, borderRadius: 40 }}
/>
</ImagePlaceholder>
);
}MIT
Made with create-react-native-library