Skip to main content

Usage

import {
FlashReels,
useFlashReels,
MuteButton,
} from 'react-native-flash-reels';
import type { ReelData } from 'react-native-flash-reels';
import { Text } from 'react-native';

type Reel = ReelData & { username: string; caption: string };

const data: Reel[] = [
{
id: '1',
videoUri: 'https://example.com/one.mp4',
posterUri: 'https://example.com/one.jpg',
duration: 12.5,
username: 'maya',
caption: 'Golden hour',
},
];

function Overlay({ item }: { item: Reel }) {
const { isMuted } = useFlashReels();
return (
<>
<MuteButton />
<Text>@{item.username}</Text>
<Text>{item.caption}</Text>
<Text>{isMuted ? 'Muted' : 'Sound on'}</Text>
</>
);
}

export function ReelsScreen() {
return (
<FlashReels
data={data}
defaultMuted
onLike={(item) => console.log('liked', item.id)}
renderOverlay={(item) => <Overlay item={item} />}
/>
);
}

Progress bar

Enable an Instagram-style bottom progress track on the built-in player:

<FlashReels data={data} showProgressBar />

Optional track styling via progressBarStyle. Ignored when renderVideo is set.

Always pass duration on each reel

The bar is currentTime / duration. Playback can start before the native player knows the clip length (especially large remote MP4s where metadata loads late). Until duration is known, the fill stays at 0 — then jumps once metadata arrives.

Pass duration (seconds) on every ReelData item so the bar tracks from the first frame:

const data: ReelData[] = [
{
id: '1',
videoUri: 'https://cdn.example.com/reel-1.mp4',
duration: 12.5, // seconds — from your API / upload pipeline
},
];

<FlashReels data={data} showProgressBar />;
SituationWhat you see
duration set on dataBar moves immediately with playback
duration omittedBar waits for onLoad / seekable range — often fine on small/local files, 3–5s+ delay (or a sudden jump) on heavy remote 4K MP4s

Where to get duration: your backend at upload/transcode time, CDN/media API, or ffprobe in a pipeline. Do not rely on the client discovering it from the file alone if you care about swipe-in UX.

Native metadata can still refine the value after onLoad; data duration is what makes the first seconds reliable.

Pagination and pull-to-refresh

Parent owns the data. Wire FlashList-style callbacks when you need infinite scroll or refresh:

<FlashReels
data={page}
onEndReached={loadMore}
onEndReachedThreshold={0.5}
refreshing={refreshing}
onRefresh={reload}
/>

onRefresh enables bounce/overscroll so the gesture works; without it, overscroll stays locked for snap paging.

Buffering loader

Show a spinner while the active reel buffers (built-in player only):

<FlashReels data={data} showBufferingLoader />

Or supply your own UI — providing renderBufferingLoader alone is enough:

<FlashReels data={data} renderBufferingLoader={() => <MySpinner />} />

Imperative ref

import { useRef } from 'react';
import { FlashReels } from 'react-native-flash-reels';
import type { FlashReelsRef } from 'react-native-flash-reels';

const ref = useRef<FlashReelsRef>(null);

ref.current?.scrollToIndex(3);
ref.current?.pause();
ref.current?.play();

Custom video engine

Pass renderVideo when you want something other than react-native-video:

<FlashReels
data={data}
renderVideo={(item, { isActive, muted }) => (
<MyPlayer uri={item.videoUri} playing={isActive} muted={muted} />
)}
/>

Controlled mute

const [muted, setMuted] = useState(true);

<FlashReels data={data} muted={muted} onMuteChange={setMuted} />;

Performance features (opt-in)

Enable HTTP/poster prefetch, poster-until-ready, and optional disk cache for snappier swipes. Full guidance (HLS ABR, CDN, ranking) is in Performance.

<FlashReels
data={data}
preloadWindowSize={1}
prefetchEnabled
prefetchWindowSize={2}
prefetchStrategy="directional"
showPosterUntilReady
posterBlurRadius={10}
videoCacheEnabled
/>
PropRole
prefetchEnabledWarm posters + tiny video Range requests (no extra decoders)
prefetchWindowSizeHow many items ahead to warm (default 2)
prefetchStrategy'directional' (bias ahead of scroll) or 'symmetric'
showPosterUntilReadyKeep posterUri visible until first frame
videoCacheEnabledRN Video disk cache (default 100 MB)

Tips:

  • Pass posterUri when using showPosterUntilReady.
  • Keep preloadWindowSize at 1 on Android unless you have headroom for more decoders.
  • On iOS, disk cache also needs $RNVideoUseVideoCaching=true in your Podfile — see Installation.
  • Optional prefetchPriority on each item (from your ranked API) controls warm-up order.