Skip to main content

React hooks

Hooks subscribe to the native event streams and manage unsubscription for you. Import them from the package root.

import {
useProgress,
usePlaybackState,
useActiveTrack,
useCanSkip,
useSleepTimer,
useBufferState,
useFullyBuffered,
useEqualizer,
useVisualizerState,
useLookaheadCache,
useNowPlayingFormat,
useCast,
useAudioRoute,
} from 'react-native-queue-player';

useProgress

useProgress(): { position: number; duration: number; buffered: number } // seconds

For a scrubber / progress bar.

usePlaybackState

usePlaybackState(): { state: PlayerState; reason: StateChangeReason }

For play/pause/loading UI. state is 'none' | 'loading' | 'buffering' | 'playing' | 'paused' | 'ended' | 'error'.

useActiveTrack

useActiveTrack(): { track: TrackItem | undefined; index: number; reason: TrackChangeReason }

The current track, its queue index, and why it last changed — delivered atomically.

useCanSkip

useCanSkip(): { canSkipNext: boolean; canSkipPrevious: boolean }

Already accounts for repeat mode. Use it to enable/disable transport buttons.

useSleepTimer

useSleepTimer(): {
active: boolean;
endsAtEpochMs?: number;
remainingSeconds?: number;
endOfTrack: boolean;
}

Reflects the current sleep timer. remainingSeconds is recomputed locally once a second from the wall-clock deadline, so a countdown label stays live between native events. Arm it with player.setSleepTimer(seconds) or player.setSleepTimerToTrackEnd(), and clear it with player.clearSleepTimer().

const timer = useSleepTimer();
// …
{timer.active && (
<Text>
{timer.remainingSeconds === undefined
? 'Stopping at end of track'
: `Sleeping in ${Math.ceil(timer.remainingSeconds / 60)} min`}
</Text>
)}

useBufferState

useBufferState(): 'empty' | 'buffering' | 'stalled' | 'full'

Reflects the current buffer state for the active track, driven by native buffer signals. Use it to drive a loading / stall indicator without polling.

const buffer = useBufferState();
// …
{buffer === 'stalled' && <Text>Rebuffering…</Text>}
{buffer === 'buffering' && <Spinner />}

useFullyBuffered

useFullyBuffered(): boolean

true once the active track has fully downloaded — distinct from useBufferState() === 'full' ("enough to keep up"). Use it to render a 100%-buffered bar or a full-length scrubber. Always false for a live / unknown-length stream.

useEqualizer

useEqualizer(): {
enabled: boolean;
bands: EqualizerBand[];
presets: EqualizerPreset[];
setEnabled(enabled: boolean): Promise<void>;
setBandGain(index: number, gainDb: number): Promise<void>;
setAllBandGains(gains: number[]): Promise<void>;
applyPreset(name: string): Promise<void>;
saveCustomPreset(name: string): Promise<void>;
deleteCustomPreset(name: string): Promise<void>;
reset(): Promise<void>;
}

State plus imperative setters for an EQ screen. See Equalizer.

useVisualizerState

useVisualizerState(config: VisualizerConfig, sampleRateHz?: number /* default 30 */): {
fft: Float32Array | null;
samples: Float32Array | null;
sampleRate: number;
available: boolean;
reason: VisualizerErrorReason | null;
}

Throttles native frames to sampleRateHz and hands you typed arrays. See Visualizer.

useLookaheadCache

useLookaheadCache(): {
status: CacheStatus;
setConfig(config: LookaheadCacheConfig): Promise<void>;
clear(): Promise<void>;
}

See Look-ahead cache.

useNowPlayingFormat

useNowPlayingFormat(): NowPlayingFormat | null

Codec / container / bitrate / ReplayGain info for the active track. See TrackPlayer.

useCast

useCast(): {
supportedProtocols: CastProtocol[];
isAvailable: boolean;
receivers: CastReceiver[];
route: CastRoute;
isDiscovering: boolean;
lastSessionDied: CastSessionDiedEvent | null;
permission: CastLocalNetworkPermission;
}

Aggregated cast state for a picker UI. See Cast manager.

useAudioRoute

useAudioRoute(): AudioRoute

The current audio output route (speaker, wired, Bluetooth, AirPlay, CarPlay, …).