PDFViewer
PDF document viewer component built on react-native-pdf with enhanced loading states, theme integration, and automatic error handling. Provides a seamless document viewing experience with smooth loading animations and consistent styling.
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
sourceURI | string | ✓ | - | URI of the PDF document to display |
containerStyle | StyleProp<ViewStyle> | - | - | Custom styles for the container view |
style | StyleProp<ViewStyle> | - | - | Custom styles for the PDF component |
testID | string | - | "pdf-viewer" | Test identifier for the component |
onLoadComplete | (numberOfPages: number, path: string, size: {width: number, height: number}, tableContents?: TableContent[]) => void | - | - | Callback when PDF loading completes |
Inherits all props from PdfProps except source
Additional Inherited Props
onError- Error handling callbackonPageChanged- Page change callbackonProgress- Loading progress callbackenablePaging- Enable page-based scrollinghorizontal- Horizontal scrolling modefitPolicy- PDF fit policy (default: 0)spacing- Page spacingpassword- PDF password if required
Component Behavior
Loading States
- Initial Loading: Shows animated loading indicator with theme-aware backdrop
- Document Ready: Displays PDF content with fade-in animation
- Error State: Handles loading failures through error callbacks
Animation System
- Uses
react-native-reanimatedfor smooth fade in/out transitions - Loading indicator appears immediately when
sourceURIis provided - Content fades in seamlessly when document is ready
Theme Integration
- Automatically applies theme colors for loading backdrop
- Respects app theme for consistent visual experience
- Uses
useAppThemehook for dynamic theming
Styling
Container Customization
const containerStyle = {
backgroundColor: '#f5f5f5',
borderRadius: 8,
margin: 16,
};
<PDFViewer
sourceURI="https://example.com/document.pdf"
containerStyle={containerStyle}
/>
PDF Content Styling
const pdfStyle = {
flex: 1,
backgroundColor: 'white',
};
<PDFViewer
sourceURI="https://example.com/document.pdf"
style={pdfStyle}
/>
Full Screen PDF
<PDFViewer
sourceURI="https://example.com/document.pdf"
containerStyle={{ flex: 1 }}
style={{ flex: 1 }}
/>
Usage Patterns
Privacy Policy Display
import * as React from "react";
import { PDFViewer } from "@ovok/native";
export const PrivacyPolicyScreen = () => {
return (
<PDFViewer
sourceURI="https://storage.example.com/privacy-policy.pdf"
testID="privacy-policy-viewer"
/>
);
};
Terms and Conditions
import * as React from "react";
import { PDFViewer } from "@ovok/native";
export const TermsScreen = () => {
const handleLoadComplete = (pages: number) => {
console.log(`Terms document has ${pages} pages`);
};
return (
<PDFViewer
sourceURI="https://storage.example.com/terms.pdf"
onLoadComplete={handleLoadComplete}
containerStyle={{ margin: 16 }}
/>
);
};
Device Instruction Manual
import * as React from "react";
import { Alert } from "react-native";
import { PDFViewer } from "@ovok/native";
interface DeviceManualProps {
deviceType: string;
manualUrl: string;
}
export const DeviceManual = ({ deviceType, manualUrl }: DeviceManualProps) => {
const handleError = (error: Error) => {
Alert.alert(
"Manual Not Available",
`Unable to load ${deviceType} instruction manual. Please try again later.`
);
};
return (
<PDFViewer
sourceURI={manualUrl}
onError={handleError}
testID={`manual-${deviceType.toLowerCase()}`}
enablePaging
horizontal={false}
/>
);
};
Healthcare Document Viewer
import * as React from "react";
import { View, StyleSheet } from "react-native";
import { ActivityIndicator, Text } from "react-native-paper";
import { PDFViewer } from "@ovok/native";
interface HealthcareDocProps {
documentId: string;
documentUrl: string;
title: string;
}
export const HealthcareDocumentViewer = ({
documentId,
documentUrl,
title
}: HealthcareDocProps) => {
const [isLoading, setLoading] = React.useState(true);
const [error, setError] = React.useState<string | null>(null);
const handleLoadComplete = () => {
setLoading(false);
setError(null);
};
const handleError = (err: Error) => {
setLoading(false);
setError(err.message);
};
if (error) {
return (
<View style={styles.errorContainer}>
<Text variant="bodyLarge">Unable to load document</Text>
<Text variant="bodyMedium">{error}</Text>
</View>
);
}
return (
<PDFViewer
sourceURI={documentUrl}
onLoadComplete={handleLoadComplete}
onError={handleError}
testID={`healthcare-doc-${documentId}`}
containerStyle={styles.container}
/>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
margin: 16,
},
errorContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 24,
},
});
Password Protected PDF
import * as React from "react";
import { PDFViewer } from "@ovok/native";
interface SecureDocumentProps {
documentUrl: string;
password: string;
}
export const SecureDocument = ({ documentUrl, password }: SecureDocumentProps) => {
return (
<PDFViewer
sourceURI={documentUrl}
password={password}
onError={(error) => {
console.error('PDF Error:', error);
}}
testID="secure-document"
/>
);
};
Error Handling
Network Errors
const handleNetworkError = (error: Error) => {
if (error.message.includes('network')) {
// Handle network connectivity issues
showNetworkErrorDialog();
} else {
// Handle other PDF errors
showGenericErrorDialog();
}
};
<PDFViewer
sourceURI={documentUrl}
onError={handleNetworkError}
/>
Validation and Fallbacks
const ValidatedPDFViewer = ({ url }: { url: string }) => {
if (!url) {
return <DocumentNotAvailable />;
}
return (
<PDFViewer
sourceURI={url}
onError={() => showDocumentErrorAlert()}
/>
);
};
Performance Considerations
Large Documents
- Use appropriate
fitPolicysettings for optimal rendering - Consider implementing pagination for very large documents
- Monitor memory usage with large PDF files
Network Optimization
- Implement proper loading states for slow connections
- Consider caching strategies for frequently accessed documents
- Handle offline scenarios gracefully
Animation Performance
- Loading animations are optimized with
react-native-reanimated - Smooth 60fps transitions without JavaScript bridge overhead
- Minimal performance impact on document rendering