React Native is an open source framework for building native mobile apps using JavaScript. Being a popular choice for mobile apps, it compiles the JavaScript components into native components to provide users with the fluid look and feel of traditional native applications. It is possible to create a cross-platform application with React Native and React that will run on both native and the web. With learn-once-write-anywhere in mind, it is more efficient for developers to create cross-platform applications with a single codebase and have it work on native and the web. This speeds up development, creates consistent UX, while still has the option to maintain the flexibility for platform-specific logic.

In this tutorial, you will learn how to create a cross-platform PDF viewer with React and React Native using PDFTron SDK and expo.

By the end of this tutorial, you will be able to build something like this:


First, let's create a simple expo app:

npm install react react-dom react-native-web
npm install expo-cli --global
expo init my-app
cd my-app
expo start

This will create an app that can work on native and the web. See detailed getting started guide from React Native for Web.

Integrate with PDFTron SDK

Next, we will add PDFTron's React Native SDK as well as WebViewer into the app.


PDFTron's React Native SDK is a native module, therefore, we will first need to eject the native modules:

expo eject

Then, follow the instructions here to add PDFTron's React Native module to the app. Follow all of the cross-platform instructions. Then, follow step 1-5 for Android, and step 1-3 for iOS.


Create a file inside the android folder with your Android SDK location, for example:


Note: replace with your actual path.


Follow the instructions here to add WebViewer to the app. Follow step 1-2.

Then, add the following to package.json:

"scripts": {
  "postinstall": "node tools/copy-webviewer-files.js"

Lastly, create a tools folder, and add the following copy-webviewer-files.js file in it:

Create the PDF Viewer

Create a components/viewer folder, then add the following files:

  • Viewer.native.tsx - the native implementation of the viewer
  • Viewer.tsx - the web implementation of the viewer
  • package.json - exports the component

Add the following to the package.json:

  "name": "Viewer",
  "version": "0.0.0",
  "private": true,
  "main": "./Viewer"

Native Viewer

Add in Viewer.native.tsx:

import React from 'react';
import {useEffect} from 'react';

import { DocumentView, RNPdftron } from 'react-native-pdftron';

type ViewerProps = {
  document: string

const MyComponent = ({ document }: ViewerProps) => {

  useEffect(() => {
    RNPdftron.initialize("Insert commercial license key here after purchase");
  }, []);

  return (

export default MyComponent;


Add in Viewer.tsx:

import React from 'react';
import {useEffect, useRef} from 'react';
import WebViewer from '@pdftron/webviewer';

type ViewerProps = {
  document: string

const MyComponent = ({ document }: ViewerProps) => {
  const viewer = useRef<HTMLDivElement>(null);

  useEffect(() => {
        path: 'lib',
        initialDoc: document,
      viewer.current as HTMLDivElement,
    ).then((instance) => {
        // you can now call WebViewer APIs here...
  }, []);

  return (
    <div className="MyComponent">
      <div className="webviewer" ref={viewer} style={{height: "100vh"}}></div>

export default MyComponent;

Use the PDF Viewer

In App.tsx, this viewer component can now be used:

return (
  <View style={styles.container}>
    <MyViewer document={""}/>

This will pick up the native component on the mobile and the WebViewer component on the web. The rest of your application can share the same code, both for business logic and the UI.

That's it!

You can find full source code from


As you can see, create a cross-platform PDF viewer that runs on both the mobile and the web using PDFTron SDK isn’t too complicated when using PDFTron's React-Native SDK, WebViewer and expo.

Get started with PDFTron for React Native and WebViewer and let us know what you build!

We hope you found this article helpful! If you have any questions or comments, don’t hesitate to contact us .