I'm creating a ReactJS app that uses QR codes and I want to be able to print a PDF document with a batch of codes at once. I'm currently using both react-qr-svg to generate the codes and @react-pdf/renderer to create the document. The problem is that I haven't been able to show these QR Codes on the document.
First I tried using the Image tag from @react-pdf/renderer like this:
<Image
src={<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>}
/>
Whick of course didn't work, after that I tried to convert the SVG to a Data Buffer and had no results.
Is there any straightforward solution for this? Should I use other libraries for this project?
Create your own PDF QR Code in 3 easy steps. Click 'Create QR Code' -> Choose 'PDF QR' type. Upload your PDF or paste the URL to the file. Customize the look and design of the QR Code as you like. Click on Next—and you're done!
Once you have a QR code that links to a website or document, you can print it and place it on various sales and marketing materials, like social media posts, one-pagers, billboards, signage, and more.
I use qrcode.react
with @react-pdf/renderer
.
First thing you need to do is to convert your QR canvas to base64
const qrCodeCanvas = document.querySelector('canvas');
const qrCodeDataUri = qrCodeCanvas.toDataURL('image/jpg', 0.3);
Then, pass base64 string (qrCodeDataUri
) as a prop to your PDF component in source of @react-pdf/renderer
image tag:
<Image source={ {uri: props.yourBase64Image} } />
Directly from the docs: https://www.npmjs.com/package/react-qr-svg
You don’t need to put it in an image tag.
My assumption is this library outputs <svg> ... </svg>
(I.e. valid HTML tags to output directly)
You can just output the tag/element out directly?
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
render() {
return (
<QRCode
bgColor="#FFFFFF"
fgColor="#000000"
level="Q"
style={{ width: 256 }}
value="some text"
/>
);
}
}
UPDATE
If I understand correctly, we cannot simply output <svg>...</svg>
on the page as the library @react-pdf/renderer will not work with svg tags. So I propose we serialize the svg to a base-64 string, assigning that to the src of the image tag and then it should work.
I put a simplified demo together without libraries:https://codepen.io/Alexander9111/pen/QWweYXO
HTML (simplified):
<svg>
<ellipse class="ground" fill="##787f6a" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path class="kiwi" fill="#94d31b" d="M210.333,65.331C104.367,...,203.01z"/>
</svg>
<div id="target">
<!-- place to put our img tag -->
</div>
JS:
const svg = document.querySelector("svg");
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = document.createElement("img")
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
const target = document.querySelector("#target");
target.appendChild(img);
svg.parentNode.removeChild(svg);
Now, if we want to do this in React, I assume we can do it something like this:
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
render() {
const svg = function {
return (<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>);
};
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img_src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
return (
<img src={ img_src }/>
);
}
}
OR we could probably do it with lifecycle hooks such as componentDidMount()
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
componentDidMount() {
const div = this.refs.target;
const svg = div.querySelector("svg");
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = this.refs.img;
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
svg.parentNode.removeChild(svg);
}
render() {
return (<div ref="target">
<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>
<img ref="img"/>
</div>
)
}
}
UPDATE - I have it working in React on CodePen: https://codepen.io/Alexander9111/pen/GRJKQQK
HTML: <div id="root"></div>
CSS: svg{border: 2px solid black;} img{border: 2px solid blue;}
React JS:
class Demo extends React.Component {
componentDidMount() {
const div = this.refs.target;
const svg = div.querySelector("svg");
console.log(svg);
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = this.refs.img;
console.log(img);
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
svg.parentNode.removeChild(svg);
}
render() {
return (
<div ref="target">
<svg width="400" height="400">
<circle r="100" cx="200" cy="200" fill="red" />
</svg>
<img ref="img"/>
</div>
);
}
}
ReactDOM.render(
<Demo/>,
document.getElementById('root')
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With