GuidesComponentsPDF

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.

  • Stable unknown
  • Release candidate since 1.16.1-rc.3
  • Development since 1.16.1-dev.2111+9796905

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

Every prop, with its type and description, is listed in the @ovok/native/pdf API reference.

Component Behavior

Loading States

  1. Initial Loading: Shows animated loading indicator with theme-aware backdrop
  2. Document Ready: Displays PDF content with fade-in animation
  3. Error State: Handles loading failures through error callbacks

Animation System

  • Uses react-native-reanimated for smooth fade in/out transitions
  • Loading indicator appears immediately when sourceURI is 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 useAppTheme hook 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/pdf";

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/pdf";

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/pdf";

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/pdf";

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/pdf";

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 fitPolicy settings 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

Last updated on

On this page