Ultra high-performance PDF viewer for React Native. Renders massive PDFs (1000+ pages) with extreme zoom levels while using minimal memory. 10x faster than native PDFKit on iOS, prevents crashes on large documents. Uses CATiledLayer (iOS) and PdfRenderer
npm install react-native-optimized-pdfHigh-performance PDF viewer for React Native with optimized memory usage. Uses CATiledLayer on iOS and PdfRenderer on Android for smooth rendering with automatic caching.
- 🚀 Optimized memory usage with CATiledLayer (iOS) and PdfRenderer (Android)
- 📦 Automatic caching with configurable expiration
- 📱 Smooth zoom and scroll with customizable maximum zoom
- 🎯 Built-in page navigation with optional custom controls
- 📊 Comprehensive event callbacks for load, error, and page events
- 🎨 High-quality rendering with antialiasing support
- 📈 Download progress tracking for remote PDFs
- ⚡ TypeScript support with full type definitions
- 🔧 Modular architecture with exportable utilities
- 🤖 Cross-platform support for iOS and Android
- 🔒 Password-protected PDF support
``bash`
npm install react-native-optimized-pdfor
yarn add react-native-optimized-pdf
`bash`
cd ios && pod install
No additional setup required! The module will be automatically linked.
`tsx
import OptimizedPdfView from 'react-native-optimized-pdf';
function App() {
return (
);
}
`
`tsx
import OptimizedPdfView from 'react-native-optimized-pdf';
function App() {
return (
uri: 'https://example.com/sample.pdf',
cache: true,
cacheFileName: 'my-custom-file.pdf',
expiration: 86400, // 24 hours in seconds
headers: {
Authorization: 'Bearer token',
},
}}
maximumZoom={5}
enableAntialiasing={true}
showNavigationControls={true}
style={{ flex: 1 }}
onLoadComplete={(page, dimensions) => {
console.log(Loaded page ${page}, dimensions);Total pages: ${count}
}}
onPageCount={(count) => {
console.log();Changed to page ${page}
}}
onPageChange={(page) => {
console.log();`
}}
onError={(error) => {
console.error('PDF Error:', error.nativeEvent.message);
}}
/>
);
}
`tsx
import OptimizedPdfView from 'react-native-optimized-pdf';
import { useState } from 'react';
function App() {
const [password, setPassword] = useState('');
const [showPasswordPrompt, setShowPasswordPrompt] = useState(false);
return (
<>
password={password}
onPasswordRequired={() => {
setShowPasswordPrompt(true);
}}
onError={(error) => {
if (error.nativeEvent.message.includes('Invalid password')) {
alert('Wrong password, please try again');
}
}}
style={{ flex: 1 }}
/>
{/ Your password input modal /}
>
);
}
`
`tsx
import OptimizedPdfView from 'react-native-optimized-pdf';
import { useState } from 'react';
import { View, Text } from 'react-native';
function App() {
const [currentPage, setCurrentPage] = useState(0);
const [totalPages, setTotalPages] = useState(1);
return (
showNavigationControls={false}
onPageCount={setTotalPages}
onPageChange={setCurrentPage}
style={{ flex: 1 }}
/>
{/ Your custom navigation UI /}
Page {currentPage + 1} of {totalPages}
);
}
`
`tsx
import { PdfCacheService } from 'react-native-optimized-pdf';
// Clear specific cache
await PdfCacheService.clearCache({ uri: 'https://example.com/file.pdf' });
// Clear all cached PDFs
await PdfCacheService.clearAllCache();
// Get cache size in bytes
const size = await PdfCacheService.getCacheSize();
console.log(Cache size: ${size / 1024 / 1024} MB);
// Check if cache is valid
const isValid = await PdfCacheService.isCacheValid({
uri: 'https://example.com/file.pdf',
expiration: 3600,
});
`
| Prop | Type | Default | Description |
| ------------------------ | ------------------------------------------------------- | ------------ | -------------------------------------- |
| source | PdfSource | required | PDF source configuration |password
| | string | - | Password for encrypted PDF files |maximumZoom
| | number | 3 | Maximum zoom level |enableAntialiasing
| | boolean | true | Enable antialiasing for better quality |showNavigationControls
| | boolean | true | Show built-in navigation controls |style
| | ViewStyle | - | Container style |onLoadComplete
| | (page: number, dimensions: PdfPageDimensions) => void | - | Called when PDF loads |onPageCount
| | (count: number) => void | - | Called when page count is available |onPageChange
| | (page: number) => void | - | Called when page changes |onError
| | (error: PdfErrorEvent) => void | - | Called on error |onPasswordRequired
| | () => void | - | Called when PDF requires a password |
| Property | Type | Default | Description |
| --------------- | ------------------------ | ------------ | ------------------------------------------------------------ |
| uri | string | required | PDF file URI (remote URL or local path) |cache
| | boolean | true | Enable local caching |cacheFileName
| | string | MD5 of URI | Custom filename for cached file |expiration
| | number | - | Cache expiration in seconds (0 or undefined = no expiration) |headers
| | Record | - | HTTP headers for download |
Static methods for managing PDF cache:
- getCacheFilePath(source: PdfSource): string - Get local cache pathisCacheValid(source: PdfSource): Promise
- - Check if cache is validdownloadPdf(source: PdfSource, onProgress?: (percent: number) => void): Promise
- - Download and cache PDFclearCache(source: PdfSource): Promise
- - Clear specific cached fileclearAllCache(): Promise
- - Clear all cached PDFsgetCacheSize(): Promise
- - Get total cache size in bytes
Reusable navigation controls component:
`tsx
import { PdfNavigationControls } from 'react-native-optimized-pdf';
totalPages={10}
onNextPage={() => {}}
onPrevPage={() => {}}
onPageChange={(page) => {}}
/>;
`
Loading state component with progress:
`tsx
import { PdfLoadingOverlay } from 'react-native-optimized-pdf';
`
Error state component:
`tsx
import { PdfErrorOverlay } from 'react-native-optimized-pdf';
`
| Platform | Supported | Min Version |
| -------- | --------- | ----------- |
| iOS | ✅ Yes | iOS 12.0+ |
| Android | ✅ Yes | API 24+ |
1. Enable caching for remote PDFs to avoid re-downloading
2. Set cache expiration for frequently updated documents
3. Use custom cache filenames for better cache management
4. Monitor cache size and clear old files periodically
5. Adjust maximum zoom based on your needs (lower = better performance)
6. Hide navigation controls if implementing custom UI
- Check that the URI is accessible
- Verify network permissions for remote URLs
- Check console for error messages
- Ensure file format is valid PDF
- Reduce maximumZoom value
- Clear cache periodically
- Use smaller PDF files when possible
- Verify write permissions
- Check available storage space
- Ensure cache is not set to false
- Use onPasswordRequired callback to prompt user for passwordpassword` prop
- Pass the password via the
- Check for "Invalid password" in error message to show retry prompt
MIT
Contributions are welcome! Please open an issue or submit a pull request.
Created with ❤️ for the React Native community