How to View a PDF in React Native Using react-native-pdf
React Native does not ship with a built-in PDF viewer, so developers rely on the react-native-pdf library to render documents from remote URLs, local file paths, or base64 data strings on both iOS and Android.
While the core React Native framework lacks native PDF capabilities, the community package react-native-pdf bridges this gap by wrapping platform-specific APIs—PDFKit on iOS and PdfRenderer on Android—into a declarative React component. According to the react-native-pdf source code, the library exposes a single Pdf component that handles binary decoding, memory management, and gesture recognition, allowing you to view a PDF in React Native using react-native-pdf with minimal native configuration.
Installation and Native Module Linking
Install the package from npm and link the native modules. For React Native 0.60 and above, autolinking handles the native side; for older versions, you must manually link.
npm install --save react-native-pdf
# or
yarn add react-native-pdf
For iOS, install the CocoaPods dependency:
cd ios && pod install && cd ..
For React Native versions below 0.60, run the manual linking command:
npx react-native link react-native-pdf
Basic Implementation with the Pdf Component
The library exports a default Pdf component from src/index.js. Import it and provide a source object containing a uri string.
import React from 'react';
import {StyleSheet, View, Dimensions} from 'react-native';
import Pdf from 'react-native-pdf';
const PdfViewer = () => {
const source = {
uri: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
cache: true, // Cache the file locally on Android
};
return (
<View style={styles.container}>
<Pdf
source={source}
style={styles.pdf}
onLoadComplete={(pageCount, filePath) => {
console.log(`PDF loaded – ${pageCount} pages`);
}}
onPageChanged={(page, pageCount) => {
console.log(`Current page: ${page}/${pageCount}`);
}}
onError={(error) => {
console.log('PDF load error:', error);
}}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
pdf: {
flex: 1,
width: Dimensions.get('window').width,
},
});
Key props:
source– An object with auriproperty pointing to a remote URL, local file path, or data URI.onLoadComplete– Callback invoked when the PDF finishes loading, receivingpageCountandfilePath.onPageChanged– Callback triggered when the user swipes to a new page.
Source Configuration: Remote, Local, and Base64 URIs
The uri string accepts multiple formats, but platform-specific path conventions apply. For local bundled assets, use conditional logic to handle iOS and Android directory structures differently.
const source = {
uri: Platform.OS === 'ios'
? `${RNFS.MainBundlePath}/sample.pdf`
: 'file:///android_asset/sample.pdf',
};
For base64-encoded PDFs, prefix the string with data:application/pdf;base64, and pass it as the uri. On Android, setting cache: true in the source object persists the file to disk, improving reload performance according to the native implementation in android/src/main/java/com/wonday/reactnativepdf/ReactNativePdfView.java.
Advanced Features and Programmatic Control
Beyond basic rendering, the component supports granular control over navigation and presentation:
- Horizontal paging – Set the
horizontalprop totrueto display pages side-by-side. - Zoom constraints – Use
maxScaleandminScaleprops to prevent excessive memory consumption when viewing large documents. - Programmatic navigation – Attach a
refto thePdfcomponent and callsetPage(pageNumber)to jump to specific pages. - Custom loading UI – Pass a React element to the
activityIndicatorprop to replace the default spinner.
Example of programmatic page control:
const pdfRef = useRef(null);
const goToPage = (pageNum) => {
pdfRef.current?.setPage(pageNum);
};
<Pdf
ref={pdfRef}
source={source}
// ... other props
/>
Native Architecture and Platform Implementations
Understanding the underlying native code helps debug rendering issues. According to the react-native-pdf source:
- Android – The view logic resides in
android/src/main/java/com/wonday/reactnativepdf/ReactNativePdfView.java, which utilizes the AndroidPdfRendererAPI introduced in API level 21 (Android 5.0). This class handles bitmap generation for pages and manages the file descriptor lifecycle. - iOS – The implementation in
ios/RCTPdfView.mleverages Apple’sPDFKitframework, specificallyPDFViewandPDFDocument, to render content and handle zoom gestures natively.
Both implementations expose a unified JavaScript interface while managing platform-specific memory optimizations internally.
Android Permissions and Security
When loading PDFs from external storage on Android, declare the required permission in android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
For Android 6.0 (API 23) and above, request this permission at runtime using a library like react-native-permissions before attempting to load local files. iOS typically does not require additional permissions for sandboxed app directories, but ensure the file path is correctly formatted without the file:// scheme prefix for PDFKit compatibility.
Common Pitfalls and Troubleshooting
- Missing native module – After installation, always rebuild the native app (
npx react-native run-androidorrun-ios). ThePdfcomponent requires the bridged native code compiled inReactNativePdfView.javaorRCTPdfView.m. - Incorrect URI schemes – Android requires the
file://prefix for absolute paths, whereas iOS accepts the raw absolute path. Using the wrong format results in a "file not found" error in theonErrorcallback. - Memory exhaustion – Extremely large PDFs can trigger out-of-memory errors on older devices. Implement pagination or use the
scaleprop to reduce initial render resolution.
Summary
- React Native lacks built-in PDF support, necessitating the
react-native-pdflibrary for native rendering. - The
Pdfcomponent acceptssourceobjects with remote URLs, local file paths, or base64 data, handlingPDFKitandPdfRenderercomplexity internally. - Platform-specific file path formatting and Android storage permissions are critical for local file display.
- Advanced features like horizontal paging, programmatic navigation via refs, and custom loading indicators provide a polished user experience.
- The native implementations in
ReactNativePdfView.java(Android) andRCTPdfView.m(iOS) manage memory and gestures, exposing a declarative JavaScript API.
Frequently Asked Questions
Does react-native-pdf work with Expo?
No, react-native-pdf requires native modules (PDFKit on iOS and PdfRenderer on Android) that must be linked at the native level, which Expo’s managed workflow does not support without ejecting to a bare workflow or using a custom development client.
How do I display a PDF from a base64 string?
Construct a data URI by prefixing your base64 string with data:application/pdf;base64,, then pass it as the uri in the source object: source={{ uri: 'data:application/pdf;base64,' + base64String }}. The library decodes this internally in the native modules for both platforms.
Why does my PDF not appear on Android?
Verify that you have requested READ_EXTERNAL_STORAGE runtime permissions for external files and that local file URIs use the file:// scheme. Additionally, ensure you have run cd android && ./gradlew clean and rebuilt the app after installation, as the native Java code in ReactNativePdfView.java must be compiled into the APK.
Can I customize the loading spinner while the PDF loads?
Yes, pass a React element to the activityIndicator prop to replace the default native spinner. This renders while the library initializes the PDFDocument (iOS) or PdfRenderer (Android) in the background.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s https://instagit.com/install.md