Download as pdf or txt
Download as pdf or txt
You are on page 1of 19

How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Open in app Sign up Sign In

Search Medium

How to build react-native bridge and get PDF


Viewer
Maksym Rusynyk · Follow
Published in DailyJS
6 min read · Apr 24, 2018

Listen Share

React Native allows to build native applications using JavaScript language and has
vast amount of components and functionality available. But some components or
features are not available by default. And sometimes it is necessary to improve
the performance of some components. In these cases native implementation can
be used.

This article describes how to make a bridge between JavaScript and a native
implementation, and provides an example how to build a PDF Viewer for React
Native to render PDF documents.

All sources are available in gitlab or as NPM package:

• NPM package react-native-view-pdf (https://www.npmjs.com/package/react-


native-view-pdf)

• Gitlab sources rumax/react-native-PDFView (https://github.com/rumax/react-


native-PDFView)

Getting started
First prepare a project. Open a terminal and run:

1 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

$ create-react-native-app react-native-PDFView
$ cd react-native-PDFView
$ yarn eject

Check that project works:

$ yarn run android

and open it in the IDE. I prefer Atom, therefore in terminal I can do:

$ atom .

Open Android Studio to work with Java sources.

Java implementation
In Android Studio:

• create new package reactlibrary

• create new Java classes PDFView , PDFViewManager and PDFViewPackage

PDFViewPackage
According to official documentation PDFViewPackage should implements
ReactPackage and missing createNativeModules and createViewManagers methods
should be added:

public class PDFViewPackage implements ReactPackage {


@Override
public List<NativeModule>
createNativeModules(ReactApplicationContext reactContext) {
return Collections.emptyList();
}

public List<ViewManager>
createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(new
PDFViewManager(reactContext));

2 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

}
}

Android Studio will highlight an error PDFViewManager cannot be applied to ... ,

which has to be fixed by implementing PDFViewManager .

PDFViewManager
PDFViewManager should extends SimpleViewManager<PDFView> and implements
missing methods:

• getName which - should return the name of the react class

• createViewInstance is a place where the viewer should be initialized

The code is:

public class PDFViewManager extends SimpleViewManager<PDFView> {


private static final String REACT_CLASS = "PDFView";
private PDFView pdfView = null;
private Context context;

public PDFViewManager(ReactApplicationContext context) {


this.context = context;
}

@Override
public String getName() {
return REACT_CLASS;
}

@Override
public PDFView createViewInstance(ThemedReactContext context)
{
if (pdfView == null) {
pdfView = new PDFView(context);
}

return pdfView;
}
}

with the error that PDFView should extend View , which has to be fixed by
implementing PDFView .

PDFView

3 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

PDFView should extends android.view.View and the implementation is pretty


simple:

public class PDFView extends android.view.View {


private ThemedReactContext context;

public PDFView(ThemedReactContext context) {


super(context);
this.context = context;
}
}

At this moment all classes are ready and PDFViewPackage can be registered.

Register PDFViewPackage
In MainApplication.java there is the getPackages method. Right below
MainReactPackage the PDFViewPackage package can be registered:

@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new PDFViewPackage()
);
}

Java initial implementation is ready!

JavaScript implementation
In Atom create a new folder PDFView and create two files:

• index.js

• RNPDFView.js

PDFView/RNPDFView.js
This is main file where the PDFView react native component should be required
and component interface has to be defined:

4 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

import { requireNativeComponent, ViewPropTypes } from 'react-


native';
import PropTypes from 'prop-types';

const componentInterface = {
name: 'PDFView',
propTypes: {
...ViewPropTypes,
},
};

export default requireNativeComponent('PDFView',


componentInterface);

At this moment only ViewPropTypes are used to check that the component is
properly defined and can be used. All other properties will be added later.

PDFView/index.js
This file is optional, and can be used as wrapper component, to handle
error/loading states, or to use flow types, etc:

/* @flow */
import React from 'react';

import RNPDFView from './RNPDFView';

type Props = {};

class PDFView extends React.Component<Props, *> {


static defaultProps = {};

constructor(props: Props) {
super(props);
}

render() {
return <RNPDFView {...this.props} />;
}
}

export default PDFView;

App.js
The bridge is ready and can be imported and used:

5 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

import PDFView from './PDFView/index';

...

return (
<View style={styles.container}>
<PDFView style={styles.pdfView} />
</View>
);

Since it implements android.view.View in Java, it also should behave as a View

react-native component. This can be checked by defining styles:

const styles = StyleSheet.create({


pdfView: {
height: 400,
width: 300,
backgroundColor: 'green',
},
...

Restart the app and you will get a green rectangle like this:

6 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Styling the component

Actually that’s all for the bridge, except properties and callbacks. And if they are
not required it is already possible to implement the component in Java.

PDF Viewer implementation


To implement PDF Viewer it is necessary to know:

• resource — String value to define the resource to render. Can be url, filePath or
base64 data

• resourceType - String value to define the resource type

7 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

And of course get some feedback from native part to JavaScript:

• onError - Callback function that has to be is invoked on error

• onLoad - Callback function that has to be is invoked on load completed

Pass properties from JavaScript


In PDFView/RNPDFView.js extend the componentInterface.propTypes with the
properties described above:

const componentInterface = {
name: 'PDFView',
propTypes: {
onError: PropTypes.func,
onLoad: PropTypes.func,
resource: PropTypes.string,
resourceType: PropTypes.string,
...ViewPropTypes,
},
};

Do the same in PDFView/index.js but using flow types:

type Props = {
onError: (Error) => void,
onLoad: () => void,
resource: string,
resourceType: 'url' | 'base64' | 'file',
};

And define method onError to pass only nativeEvent from the component:

onError: (error: Error) => void; // Flow type definition


onError(event: any) {
this.props.onError(event && event.nativeEvent || new Error());
}

Do not forget to bind this in constructor:

8 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

constructor(props: Props) {
super(props);
this.onError = this.onError.bind(this);
}

And fix the render method:

render() {
const { onError, ...remainingProps } = this.props;
return <RNPDFView {...remainingProps} onError={this.onError} />;
}

Also default properties can be defined to simplify the usage of the component:

static defaultProps = {
onError: () => {},
onLoad: () => {},
resourceType: 'url',
};

The JavaScript implementation is finished now.

Get and use properties in Java


Switch to Android Studio and open PDFViewManager class. This is the place where
all properties, defined in JavaScript , can be accessed. Define resource :

@ReactProp(name = "resource")
public void setResource(PDFView pdfView, String resource) {
pdfView.setResource(resource);
}

And the same for resourceType (Callbacks will be implement later):

@ReactProp(name = "resourceType")
public void setResourceType(PDFView pdfView, String resourceType)

9 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

{
pdfView.setResourceType(resourceType);
}

Implementation in PDFView class will be:

private String resourceType;


private String resource;

public void setResource(String resource) {


this.resource = resource;
}

public void setResourceType(String resourceType) {


this.resourceType = resourceType;
}

In PDFViewManager find the following methods:

• onAfterUpdateTransaction this is the place where the component should be


rendered after all properties are set:

@Override
public void onAfterUpdateTransaction(PDFView pdfView) {
super.onAfterUpdateTransaction(pdfView);
pdfView.render();
}

• onDropViewInstance this is another method that is called when the React


Native component is unmounted. The implementation can be the following:

@Override
public void onDropViewInstance(PDFView pdfView) {
super.onDropViewInstance(pdfView);
pdfView.onDrop();
}

Use JavaScript callbacks in Java


To use load complete, error callbacks it is necessary to pass this events. Open

10 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

PDFView.java and define loadComplete and onError methods:

@Override
public void loadComplete(int numberOfPages) {
reactNativeEvent("onLoad", null);
}

@Override
public void onError(Exception ex) {
reactNativeEvent("onError", "error: " + t.getMessage());
}

and implement reactNativeEvent method. According to official documentation it


should be:

private void reactNativeEvent(String eventName, String message) {


WritableMap event = Arguments.createMap();
event.putString("message", message);
ReactContext reactContext = (ReactContext) this.getContext();
reactContext
.getJSModule(RCTEventEmitter.class)
.receiveEvent(this.getId(), eventName, event);
}

And in PDFViewManager

public Map getExportedCustomBubblingEventTypeConstants() {


return MapBuilder
.builder()
.put(
"onLoad",
MapBuilder.of("phasedRegistrationNames",
MapBuilder.of("bubbled", "onLoad"))
)
.put(
"onError",
MapBuilder.of("phasedRegistrationNames",
MapBuilder.of("bubbled", "onError"))
)
.build();
}

11 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

The implementation of the bridge is ready! The only thing left to do is to


implement PDFViewer.java . I used AndroidPdfViewer implementation and final
solution you can find in gitlab (https://github.com/rumax/react-native-PDFView).

Results
The implementation of the bridge and PDF Viewer is ready. Define the document
you would like to render:

<View style={styles.container}>
<PDFView
style={styles.pdfView}
React Native Pdf JavaScript Native App Components
onError={error => console.log('onError', error) }
onLoad={() => console.log('onLoad') }
resource="http://www.pdf995.com/samples/pdf.pdf" />
</View>

..reload the application and instead of green rectangle you will get PDF
document:

Follow

Written by Maksym Rusynyk


106 Followers · Writer for DailyJS

Software Engineer at ING. www.linkedin.com/in/maksymru and http://github.com/rumax/

More from Maksym Rusynyk and DailyJS

12 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Maksym Rusynyk in ITNEXT

You don’t need GUI — how to control iOS Simulator from command line
Back in past, if you used a computer, you mostly used a command line user interface. Today
for development you use GUI (Xcode, Simulator…

6 min read · Aug 11, 2018

119 3

PDF Viewer results

13 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Franziska Hinkelmann in DailyJS

How to use npm-link


Writing Application and Dependency Code Simultaneously

3 min read · Oct 19, 2018

4.6K 17

Olivier De Meulder in DailyJS

I never understood JavaScript closures


Until someone explained it to me like this …

17 min read · Sep 7, 2017

56K 253

14 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Maksym Rusynyk in ITNEXT

Azure DevOps and React Native UI testing part 2 - Android


Recommended
In from
Azure DevOps and ReactMedium
Native UI testing it was described how to implement UI testing
for iOS applications using Azure DevOps. But…

2 min read · Jun 17, 2020

57

See all from Maksym Rusynyk

See all from DailyJS

15 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Softworth Solutions Private Limited

Expo vs React Native CLI


Expo or React Native CLI ? What should i choose ?

4 min read · Jun 27

15

Bryn Bodayle in The Airbnb Tech Blog

Unlocking SwiftUI at Airbnb


How Airbnb adopted SwiftUI in our iOS app

10 min read · Sep 21

2.5K 29

Lists

Stories to Help You Grow as a Software Developer


19 stories · 423 saves

It's never too late or early to start something


15 stories · 144 saves

General Coding Knowledge


20 stories · 400 saves

Modern Marketing
34 stories · 163 saves

16 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Dmitry Kruglov in Better Programming

The Architecture of a Modern Startup


Hype wave, pragmatic evidence vs the need to move fast

16 min read · Nov 7, 2022

6.1K 59

17 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Adham Dannaway in UX Planet

16 little UI design rules that make a big impact


A UI design case study to redesign an example user interface using logical rules or
guidelines

14 min read · Mar 14

18.5K 152

AL Anany

The ChatGPT Hype Is Over — Now Watch How Google Will Kill ChatGPT.
It never happens instantly. The business game is longer than you know.

· 6 min read · Sep 1

11.2K 353

18 sur 19 04/10/2023 13:11


How to build react-native bridge and get PDF Viewer |... https://medium.com/dailyjs/how-to-build-react-native-...

Nikhil Vemu in Mac O’Clock

Change These 12 iOS 17 Settings Right Now For a Superior Experience


iOS 17’s got hell-a-lot features you can’t discover thyself

· 9 min read · Sep 26

2.3K 29

See more recommendations

19 sur 19 04/10/2023 13:11

You might also like