13

I would like to know how it's possible to include an external JavaScript library in a react project. For example, I would like to import the jspdf library : https://github.com/MrRio/jsPDF/blob/master/jspdf.js and use it in my reactjs app.

So far I tried to use require like this : 

let React = require('react');
let { Spacing, Typography } = Styles;
let DoughnutChart = require("react-chartjs").Doughnut;
let Chart = require('react-google-charts').Chart;
let { StylePropable, StyleResizable } = Mixins;
let EditableDiv = require('../EditableDiv.jsx');
//some other library
//the library that matter for me
var pdfConverter = require('../utils/jspdf.source.js');

//then I have my classical react code which works and a function to generate ad pdf
_generatePdf: function(){
    console.log('Genrating pdf');
    var doc = new pdfConverter.jsPDF('p','pt');
    var img = new Image();
}

I have the following error : TypeError: pdfConverter.jsPDF is not a function.

To make it work, I made something ugly, I copy the source of jspdf-source.js into my react.jsx file and just call jsPDF instead of pdfConverter.jsPDF. It's definitely no the right way, but can't succeed to import and use the library.

Can you tell me what I'm doing wrong and how I can correct this?

-EDIT-

When I was using my ugly solution (copying the source into my file) I just had to do the following :

var doc = new jsPDF('p','pt);

And it was working perfectly, expect that I had a very big file

After the suggested solution from @dannyjolie bellow, I've imported jspdf directly from the npm package, but I'm still not able to use the library. I tried the following code which lead to an error:

var pdfConverter = require('jspdf');
var converter = new pdfConverter();
var doc = converter.jsPDF('p', 'pt');

TypeError: pdfConverter is not a constructor Meaning that I have to import the jsPDF coming from the package, not only jspdf?

Then I tried

let pdfConverter = require('jspdf');
var converter = pdfConverter.jsPDF;
var doc = new converter('p', 'pt');

ReferenceError: jsPDF is not defined

TypeError: converter is not a constructor

Ok, obviously, I'm not importing the right thing or not the right way. What I'm doing wrong?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
FLCcrakers
  • 345
  • 1
  • 4
  • 17

3 Answers3

12

If you include the external js file link in your /public/index.html, you can use the external library with the window prefix.

Take JQuery as an example. Put the following line in your /public/index.html:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

Use it in your project like so:

window.$("#btn1").click(function(){
  alert("Text: " + $("#test").text());
});
Jason Kao
  • 1,024
  • 11
  • 15
10

First of all, don't use the source file. Just npm install jspdf --save like any other package, and import it with var pdfConverter = require('jspdf');

Secondly, you're missing a () in this line var doc = new pdfConverter.jsPDF('p','pt');

Do something like this:

var converter = new pdfConverter();
var doc = converter.jsPDF('p', 'pt');
dannyjolie
  • 10,959
  • 3
  • 33
  • 28
  • Thanks for your answer. I didn't know I can install jspdf with npm. Is it possible for any library ? (I'm quite new to npm). However it still not work as expected. When I try var converter new pdfConverter(); I get this message TypeError: pdfConverter is not a constructor. I'm still missing something but don't know what. – FLCcrakers Mar 17 '16 at 22:03
  • @FrankHOONAKKER In this case it was a lucky hunch :) https://www.npmjs.com/package/jspdf. I haven't used jsPDF much myself, I think I tried it once, but judging by the code examples the initialization is a bit different than the code you've provided. You'll probably figure it out. – dannyjolie Mar 17 '16 at 22:12
  • I still can't figure out how to do this properly. I certainly miss something. Later when I was copying the source code I could just use it like in the doc "var doc = new jsPDF();" but know that I've imported through npm I not able to find the right way… I certainly miss some knowedge but don't know which one. – FLCcrakers Mar 18 '16 at 08:51
  • Yeah, I see. I've been trying to trick it into behaving, but the only way I've come up with so far is to use a good old fashion script tag with jspdf and work with the global jsPDF function. Bummer. – dannyjolie Mar 18 '16 at 09:17
  • Good to know, I was starting to feel crazy about this.You mean that if I put a script tag including my library in my index.html I should be able to reach the global jsPDF ? I had a quick try, but not sure how to do it properly with reactjs. – FLCcrakers Mar 18 '16 at 09:44
  • Correct, just put `` in the head or whatever, and the global jsPDF function will be available. Your linter, if you use one, will protest, but in the lint config you add jsPDF as a global. In eslint that would be `"globals": {"jsPDF": true}` – dannyjolie Mar 18 '16 at 09:51
  • Yes it's working ! thanks a lot ! This mean that I would be able to do the same for any other library that is not in npm and I have an other one in mind right now. – FLCcrakers Mar 18 '16 at 10:02
  • Basically, yes. In an ideal world, libraries should expose predictable modules, but for those that don't and still stick to old school styles, doing it this way *should* work most of the time. – dannyjolie Mar 18 '16 at 10:07
  • here you go: `var jsPDF = require('jspdf'); var doc = new jsPDF('p', 'pt');` – avimak Jan 18 '17 at 21:48
3

I know this is old, but I thought it would be helpful if someone posted a full working sample. It took me a while to figure this out, using this other post as a starting point:

How to make PDF from React?

Assuming you are using create-react-app, overwrite your App.js with the following below...

import React, { Component } from 'react';
import pdfConverter from 'jspdf';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.onClick = this.onClick.bind(this);
    this.toDataUrl = this.toDataUrl.bind(this);
  }

  toDataUrl(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
      var reader = new FileReader();
      reader.onloadend = function() {
        callback(reader.result);
      }
      reader.readAsDataURL(xhr.response);
    };
    xhr.open('GET', url);
    xhr.responseType = 'blob';
    xhr.send();
  }

  onClick() {
      var doc = new pdfConverter('p','pt','letter');
      //console.log(doc.getFontList() );
      this.toDataUrl('background.jpg', function(base64Img) {
        var imgData = base64Img;
        console.log(imgData);
        console.log('Adding to doc.');
        doc.addImage(imgData, 'JPEG', 0, 0, 612, 792);
        console.log('Image added.');
        doc.setFont('Times', 'Roman');
        doc.setFontSize(22);
        doc.text(20, 50, 'Park Entry Ticket');
        doc.setFontSize(16);
        doc.text(20, 80, 'Address1: ' );
        doc.text(20, 100, 'Address2: ' );
        doc.text(20, 120, 'Entry Date & time: ');
        doc.text(20, 140, 'Expiry date & time: ' );
        console.log('About to save');
        doc.save("test.pdf");
      });
  }

  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
            <input type='button'
        onClick={this.onClick} value="Print"/>
        </p>
      </div>
    );
  }
}

export default App;
Community
  • 1
  • 1
James Young
  • 1,372
  • 13
  • 16
  • Note that the background.jpg is sitting in the public folder. toDataUrl comes from here: http://stackoverflow.com/questions/6150289/how-to-convert-image-into-base64-string-using-javascript/20285053?s=1|0.0000#20285053 – James Young Mar 24 '17 at 19:32
  • Thank you very much for this. Not yet tested, but seems to be interesting ! – FLCcrakers Jun 08 '17 at 14:34
  • When you state import pdfConverter from 'jspdf'... where do you include the library script? In index.html or as a node module? – Sebastiandg7 Sep 11 '17 at 21:56