Skip to main content

Core Features

react-native-pdf-jsi provides everything you need for professional PDF viewing in React Native. This page covers all the essential features that work out of the box.

PDF Viewing Basics

Simple PDF Viewer

The most basic PDF viewer requires just 3 lines of code:

const PdfModule = require('react-native-pdf-jsi');
const Pdf = PdfModule.default;

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
style={{ flex: 1 }}
/>

That's it! You now have a fully functional PDF viewer with:

  • ⚡ Automatic JSI acceleration (80x faster)
  • 📄 Lazy loading for large files
  • 🎯 Smart 30-day caching
  • 🔍 Zoom and pan gestures
  • 📱 Cross-platform support

Loading PDF Files

react-native-pdf-jsi supports multiple source types:

From URL

<Pdf source={{ uri: 'https://example.com/document.pdf' }} />

From Local File

<Pdf source={{ uri: 'file:///path/to/document.pdf' }} />

From Base64

<Pdf source={{ 
uri: 'data:application/pdf;base64,JVBERi0xLjcKCjEgMCBvYmogICUgZW50...'
}} />

From App Assets

iOS:

<Pdf source={require('./assets/document.pdf')} />

Android:

<Pdf source={{ uri: 'bundle-assets://document.pdf' }} />

Caching System

Automatic Caching

PDFs are automatically cached for 30 days to improve performance:

<Pdf 
source={{
uri: 'https://example.com/document.pdf',
cache: true, // Enable caching (default: true)
expiration: 30, // Days until cache expires
cacheFileName: 'my-custom-name.pdf' // Optional custom name
}}
/>

Cache Benefits

  • 📥 One-time download - PDF downloads once, then loads instantly
  • 💾 Offline access - View previously loaded PDFs without internet
  • Instant loading - Cached PDFs load in milliseconds
  • 🔄 Auto-refresh - Cache expires after 30 days and reloads

Viewing Modes

Vertical Scrolling (Default)

Standard vertical page scrolling:

<Pdf 
source={{ uri: 'https://example.com/document.pdf' }}
horizontal={false} // Vertical mode
/>

Horizontal Scrolling

Swipe left/right to change pages:

<Pdf 
source={{ uri: 'https://example.com/document.pdf' }}
horizontal={true} // Horizontal mode
/>

Single Page Mode

Show one page at a time with page indicators:

<Pdf 
source={{ uri: 'https://example.com/document.pdf' }}
singlePage={true}
enablePaging={true}
/>

Controlled Page Navigation

Control which page is displayed:

import React, { useState } from 'react';
import { View, Button } from 'react-native';
const PdfModule = require('react-native-pdf-jsi');
const Pdf = PdfModule.default;

export default function App() {
const [page, setPage] = useState(1);

return (
<View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row', padding: 10 }}>
<Button
title="Previous"
onPress={() => setPage(p => Math.max(1, p - 1))}
/>
<Button
title="Next"
onPress={() => setPage(p => p + 1)}
/>
</View>

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
page={page}
onPageChanged={(newPage) => setPage(newPage)}
style={{ flex: 1 }}
/>
</View>
);
}

Jump to Specific Page

const pdfRef = useRef(null);

// Jump to page 10
pdfRef.current?.setPage(10);

Zoom and Scaling

Zoom Controls

Configure zoom behavior:

<Pdf 
source={{ uri: 'https://example.com/document.pdf' }}
scale={1.0} // Initial zoom level
minScale={0.5} // Minimum zoom (50%)
maxScale={3.0} // Maximum zoom (300%)
onScaleChanged={(scale) => {
console.log(`Zoom level: ${scale}`);
}}
/>

Fit Policies

Control how PDFs fit on screen:

<Pdf 
source={{ uri: 'https://example.com/document.pdf' }}
fitPolicy={0} // 0=FitWidth, 1=FitHeight, 2=FitBoth
/>

Fit Policy Options:

  • 0 - FitWidth: Fit to screen width, scroll vertically
  • 1 - FitHeight: Fit to screen height, scroll horizontally
  • 2 - FitBoth: Fit entire page in viewport (default)

Double-Tap Zoom

Double-tap any area to zoom in/out automatically. This is enabled by default.

Password Protection

Password-Protected PDFs

import React, { useState } from 'react';
import { View, TextInput, Button } from 'react-native';
const PdfModule = require('react-native-pdf-jsi');
const Pdf = PdfModule.default;

export default function App() {
const [password, setPassword] = useState('');
const [unlocked, setUnlocked] = useState(false);

if (!unlocked) {
return (
<View style={{ padding: 20 }}>
<TextInput
placeholder="Enter PDF password"
value={password}
onChangeText={setPassword}
secureTextEntry
style={{ borderWidth: 1, padding: 10, marginBottom: 10 }}
/>
<Button title="Unlock PDF" onPress={() => setUnlocked(true)} />
</View>
);
}

return (
<Pdf
source={{ uri: 'https://example.com/protected.pdf' }}
password={password}
onError={(error) => {
if (error.message.includes('password')) {
alert('Incorrect password');
setUnlocked(false);
}
}}
style={{ flex: 1 }}
/>
);
}

Gestures and Interactions

Pan and Scroll

Users can:

  • Swipe - Navigate between pages
  • Pan - Move around zoomed content
  • Pinch - Zoom in/out
  • Double-tap - Quick zoom toggle

Single Tap Detection

Detect when user taps on a page:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
onPageSingleTap={(page, x, y) => {
console.log(`Tapped page ${page} at coordinates (${x}, ${y})`);
// Show/hide toolbar, etc.
}}
/>

Handle hyperlinks in PDFs:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
onPressLink={(url) => {
console.log(`Link pressed: ${url}`);
// Open in browser, handle custom URLs, etc.
}}
/>

Scroll Behavior

Scroll Indicators

Control scroll bar visibility:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
showsHorizontalScrollIndicator={true}
showsVerticalScrollIndicator={true}
/>

Enable/Disable Scrolling

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
scrollEnabled={true} // Set to false to disable scrolling
/>

Page Spacing

Adjust spacing between pages:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
spacing={10} // Pixels between pages (default: 10)
/>

Rendering Options

Anti-Aliasing

Smooth text and graphics rendering:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
enableAntialiasing={true} // Default: true
/>

Annotation Rendering

Show PDF annotations and forms:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
enableAnnotationRendering={true} // Default: true
/>

RTL Support

Right-to-left language support:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
enableRTL={true} // For Arabic, Hebrew, etc.
/>

Event Handlers

Load Complete

Triggered when PDF finishes loading:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
onLoadComplete={(numberOfPages, filePath, size, tableContents) => {
console.log(`Loaded ${numberOfPages} pages`);
console.log(`File path: ${filePath}`);
console.log(`Size: ${size.width}x${size.height}`);
console.log(`Table of contents:`, tableContents);
}}
/>

Page Changed

Triggered when user navigates to a different page:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
onPageChanged={(page, numberOfPages) => {
console.log(`Now on page ${page} of ${numberOfPages}`);
// Update UI, track analytics, etc.
}}
/>

Error Handling

Handle loading errors:

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
onError={(error) => {
console.error('PDF Error:', error);

if (error.message.includes('404')) {
alert('PDF not found');
} else if (error.message.includes('password')) {
alert('Password required');
} else {
alert(`Failed to load PDF: ${error.message}`);
}
}}
/>

Load Progress

Track download progress:

<Pdf
source={{ uri: 'https://example.com/large-document.pdf' }}
onLoadProgress={(percent) => {
console.log(`Loading: ${(percent * 100).toFixed(0)}%`);
}}
/>

Custom Loading Indicator

Replace the default loading indicator:

import { ActivityIndicator } from 'react-native';

<Pdf
source={{ uri: 'https://example.com/document.pdf' }}
renderActivityIndicator={(progress) => (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#0066cc" />
<Text>{`${(progress * 100).toFixed(0)}% loaded`}</Text>
</View>
)}
/>

Network Configuration

Trust All Certificates

For development or self-signed certificates:

<Pdf
source={{ uri: 'https://self-signed.example.com/document.pdf' }}
trustAllCerts={true} // Default: true
/>
Security Note

Only use trustAllCerts={true} in development. In production, use valid SSL certificates.

Custom Headers

Pass custom HTTP headers:

<Pdf
source={{
uri: 'https://api.example.com/document.pdf',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Custom-Header': 'value'
}
}}
/>

Custom HTTP Method

Use POST or other methods:

<Pdf
source={{
uri: 'https://api.example.com/generate-pdf',
method: 'POST',
body: JSON.stringify({ documentId: '123' }),
headers: {
'Content-Type': 'application/json'
}
}}
/>

Complete Example

Here's a full-featured PDF viewer with all core features:

import React, { useState, useRef } from 'react';
import { View, Button, Text, StyleSheet, ActivityIndicator } from 'react-native';
const PdfModule = require('react-native-pdf-jsi');
const Pdf = PdfModule.default;

export default function PDFViewer() {
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const [scale, setScale] = useState(1.0);
const [loading, setLoading] = useState(true);
const pdfRef = useRef(null);

return (
<View style={styles.container}>
{/* Header with controls */}
<View style={styles.header}>
<Text style={styles.pageText}>
Page {currentPage} of {totalPages}
</Text>
<Text style={styles.zoomText}>
Zoom: {(scale * 100).toFixed(0)}%
</Text>
</View>

{/* Navigation buttons */}
<View style={styles.controls}>
<Button
title="◀ Prev"
onPress={() => pdfRef.current?.setPage(currentPage - 1)}
disabled={currentPage <= 1}
/>
<Button
title="Next ▶"
onPress={() => pdfRef.current?.setPage(currentPage + 1)}
disabled={currentPage >= totalPages}
/>
<Button
title="Go to 10"
onPress={() => pdfRef.current?.setPage(10)}
/>
</View>

{/* PDF Viewer */}
<Pdf
ref={pdfRef}
source={{
uri: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
cache: true,
expiration: 30
}}
page={currentPage}
scale={scale}
minScale={0.5}
maxScale={3.0}
horizontal={false}
fitPolicy={0}
spacing={10}
enableAntialiasing={true}
enableAnnotationRendering={true}
onLoadComplete={(pages, path) => {
setTotalPages(pages);
setLoading(false);
console.log(`PDF loaded: ${pages} pages`);
}}
onPageChanged={(page, pages) => {
setCurrentPage(page);
}}
onScaleChanged={(newScale) => {
setScale(newScale);
}}
onError={(error) => {
console.error('PDF Error:', error);
setLoading(false);
}}
onPageSingleTap={(page) => {
console.log(`Tapped page ${page}`);
}}
renderActivityIndicator={(progress) => (
<View style={styles.loading}>
<ActivityIndicator size="large" color="#0066cc" />
<Text style={styles.loadingText}>
{`${(progress * 100).toFixed(0)}%`}
</Text>
</View>
)}
style={styles.pdf}
/>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 16,
backgroundColor: '#0066cc',
},
pageText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
zoomText: {
color: 'white',
fontSize: 16,
},
controls: {
flexDirection: 'row',
justifyContent: 'space-around',
padding: 10,
backgroundColor: 'white',
},
pdf: {
flex: 1,
},
loading: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
loadingText: {
marginTop: 10,
fontSize: 16,
color: '#666',
},
});

Platform-Specific Behavior

iOS

  • Uses PDFKit for native rendering
  • Smooth scrolling and animations
  • Full annotation support
  • Better memory management

Android

  • Uses Pdfium for rendering
  • JSI acceleration available
  • Google Play 16KB compliant
  • Optimized for large files

Windows (Experimental)

  • Uses standard bridge mode
  • Basic PDF viewing
  • Limited JSI support

Best Practices

Performance Optimization

  1. Enable caching for frequently accessed PDFs
  2. Use appropriate fit policy for your layout
  3. Disable unused features (annotations if not needed)
  4. Monitor memory with large PDFs

Error Handling

Always implement onError handler:

onError={(error) => {
// Log to analytics
console.error('PDF Error:', error);

// Show user-friendly message
Alert.alert('Error', 'Failed to load PDF');

// Provide fallback options
showFallbackUI();
}}

User Experience

  1. Show loading indicators during download
  2. Display page numbers for context
  3. Provide navigation controls for easy access
  4. Handle edge cases (no internet, invalid PDF, etc.)

Troubleshooting

PDF Not Loading

  1. Check URL is accessible
  2. Verify network permissions
  3. Check for HTTPS/HTTP issues
  4. Enable trustAllCerts for development

Slow Performance

  1. Enable caching
  2. Reduce initial scale
  3. Use appropriate fit policy
  4. Check JSI is working (see JSI Acceleration)

Memory Issues

  1. Clear old cache files
  2. Reduce max scale
  3. Use lazy loading
  4. Monitor memory usage

Next Steps

Now that you understand the core features, explore advanced capabilities:

Need the complete API reference? Check out the PDF Component API.