A react native PDF view component for displaying PDF documents from various sources with caching support.
—
Comprehensive event system for PDF loading, page navigation, user interactions, and error handling with detailed callback information. This covers all events and callbacks available in the PDF component.
Handle PDF loading progress and completion events.
/**
* PDF loading event handlers
* Monitor PDF download and loading progress
*/
interface LoadingEvents {
/**
* Called during PDF download/loading progress
* @param percent - Loading progress from 0 to 1
*/
onLoadProgress?: (percent: number) => void;
/**
* Called when PDF loading is complete
* @param numberOfPages - Total number of pages in the PDF
* @param path - Local file path where PDF is stored
* @param size - PDF dimensions in points
* @param tableContents - PDF table of contents (optional)
*/
onLoadComplete?: (
numberOfPages: number,
path: string,
size: { height: number; width: number },
tableContents?: TableContent[]
) => void;
}
type TableContent = {
/** Nested table of contents items */
children: TableContent[];
/** Native pointer reference */
mNativePtr: number;
/** Page index for this item */
pageIdx: number;
/** Display title for this item */
title: string;
};Usage Examples:
<Pdf
source={{ uri: "https://example.com/large-document.pdf" }}
onLoadProgress={(progress) => {
console.log(`Loading: ${Math.round(progress * 100)}%`);
// Update progress bar, loading indicator, etc.
}}
onLoadComplete={(numberOfPages, filePath, { width, height }, tableContents) => {
console.log(`Loaded ${numberOfPages} pages`);
console.log(`PDF size: ${width}x${height} points`);
console.log(`Cached at: ${filePath}`);
if (tableContents) {
console.log("Table of contents available:");
tableContents.forEach(item => {
console.log(`- ${item.title} (page ${item.pageIdx + 1})`);
});
}
}}
style={{ flex: 1 }}
/>Handle page navigation and current page changes.
/**
* Page navigation event handlers
* Monitor user navigation through PDF pages
*/
interface NavigationEvents {
/**
* Called when the current page changes
* @param page - Current page number (1-based)
* @param numberOfPages - Total number of pages
*/
onPageChanged?: (page: number, numberOfPages: number) => void;
}Usage Example:
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
<Pdf
source={{ uri: "document.pdf" }}
onPageChanged={(page, total) => {
setCurrentPage(page);
setTotalPages(total);
console.log(`Page ${page} of ${total}`);
}}
style={{ flex: 1 }}
/>
// Display page indicator
<Text>{`${currentPage} / ${totalPages}`}</Text>Handle user touch interactions and gestures.
/**
* User interaction event handlers
* Respond to touch gestures and user interactions
*/
interface InteractionEvents {
/**
* Called when user single-taps on a page
* @param page - Page number that was tapped (1-based)
* @param x - X coordinate of tap relative to page
* @param y - Y coordinate of tap relative to page
*/
onPageSingleTap?: (page: number, x: number, y: number) => void;
/**
* Called when zoom scale changes
* @param scale - New scale factor
*/
onScaleChanged?: (scale: number) => void;
/**
* Called when user taps on a link within the PDF
* @param url - URL or link destination
*/
onPressLink?: (url: string) => void;
}Usage Examples:
<Pdf
source={{ uri: "interactive-document.pdf" }}
onPageSingleTap={(page, x, y) => {
console.log(`Tapped page ${page} at coordinates (${x}, ${y})`);
// Show context menu, add annotation, etc.
}}
onScaleChanged={(scale) => {
console.log(`Zoom level: ${Math.round(scale * 100)}%`);
// Update zoom controls, save preference, etc.
}}
onPressLink={(url) => {
console.log(`Link pressed: ${url}`);
// Handle external links
if (url.startsWith('http')) {
Linking.openURL(url);
}
}}
style={{ flex: 1 }}
/>Handle errors during PDF loading and rendering.
/**
* Error handling
* Handle various error conditions during PDF operations
*/
interface ErrorEvents {
/**
* Called when an error occurs during PDF loading or rendering
* @param error - Error object with details about the failure
*/
onError?: (error: Error) => void;
}Usage Examples:
<Pdf
source={{ uri: "https://example.com/document.pdf" }}
onError={(error) => {
console.error("PDF Error:", error);
// Handle different error types
if (error.message?.includes("404")) {
Alert.alert("Error", "PDF document not found");
} else if (error.message?.includes("password")) {
Alert.alert("Error", "PDF requires a password");
} else if (error.message?.includes("network")) {
Alert.alert("Error", "Network error loading PDF");
} else {
Alert.alert("Error", "Failed to load PDF");
}
}}
style={{ flex: 1 }}
/>Comprehensive example showing all event handlers working together.
/**
* Complete event handling setup
* Example showing all available event handlers
*/
interface CompleteEvents extends LoadingEvents, NavigationEvents, InteractionEvents, ErrorEvents {}Complete Usage Example:
import React, { useState } from "react";
import { View, Text, Alert, ActivityIndicator } from "react-native";
import Pdf from "react-native-pdf";
export default function CompletePdfViewer() {
const [loading, setLoading] = useState(true);
const [progress, setProgress] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const [scale, setScale] = useState(1);
return (
<View style={{ flex: 1 }}>
{/* Status bar */}
<View style={{ flexDirection: "row", justifyContent: "space-between", padding: 10 }}>
<Text>Page: {currentPage}/{totalPages}</Text>
<Text>Zoom: {Math.round(scale * 100)}%</Text>
</View>
<Pdf
source={{
uri: "https://example.com/document.pdf",
cache: true
}}
// Loading events
onLoadProgress={(percent) => {
setProgress(percent);
console.log(`Loading progress: ${Math.round(percent * 100)}%`);
}}
onLoadComplete={(numberOfPages, filePath, { width, height }, tableContents) => {
setLoading(false);
setTotalPages(numberOfPages);
console.log(`PDF loaded: ${numberOfPages} pages, ${width}x${height}px`);
if (tableContents?.length) {
console.log("Table of contents:", tableContents);
}
}}
// Navigation events
onPageChanged={(page, total) => {
setCurrentPage(page);
console.log(`Navigated to page ${page} of ${total}`);
}}
// Interaction events
onPageSingleTap={(page, x, y) => {
console.log(`Single tap on page ${page} at (${x}, ${y})`);
// Could show/hide controls, add annotations, etc.
}}
onScaleChanged={(newScale) => {
setScale(newScale);
console.log(`Scale changed to ${newScale}`);
}}
onPressLink={(url) => {
console.log(`Link pressed: ${url}`);
Alert.alert("Link", `Open ${url}?`);
}}
// Error handling
onError={(error) => {
setLoading(false);
console.error("PDF Error:", error);
Alert.alert("Error", "Failed to load PDF document");
}}
style={{ flex: 1 }}
/>
{/* Loading overlay */}
{loading && (
<View style={{
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(255,255,255,0.8)"
}}>
<ActivityIndicator size="large" />
<Text>{Math.round(progress * 100)}% loaded</Text>
</View>
)}
</View>
);
}Understanding when events are triggered during PDF lifecycle.
/**
* Event lifecycle and timing
* Order and timing of events during PDF operations
*/
interface EventLifecycle {
// 1. Loading starts - component mounts
// 2. onLoadProgress - called repeatedly during download
// 3. onLoadComplete - called when PDF is ready
// 4. onPageChanged - called for initial page and navigation
// 5. onPageSingleTap - called on user interaction
// 6. onScaleChanged - called on zoom changes
// 7. onPressLink - called when links are tapped
// 8. onError - called if any errors occur
}Install with Tessl CLI
npx tessl i tessl/npm-react-native-pdf