Search code examples
htmlreact-nativeexpoqr-code

not displaying qr code in HTML print preview in react native


I am pretty new to react native. I have a React Native application (expo managed) where I generate a QR code as an SVG using the react-native-qrcode-svg library. I want to include this QR code in an HTML template and print it. I use expo print to do it.

I tried to include it in the html template by using the placeholder ${} However, when I try to display the QR code in the print preview, I can only see the headline, and the QR code appears as [object Object].

I have verified that the QRCODE component generates a valid SVG string. However, the QR code is not displayed correctly in the print preview.

Despite my efforts of trying to find a solution online, I'm still unable to display the QR code in the print preview. Any guidance or suggestions on how to resolve this issue would be greatly appreciated. Thank you! QRscreen component:

import { View, Text, TouchableOpacity } from "react-native";
import { StyleSheet } from "react-native";
import * as Print from "expo-print";

import QRCODE from "../components/QRCODE";

function QRscreen({ route, navigation }) {
  const { currentDate, currentTime, location, qrText } = route.params;

  const qrCodeData = JSON.stringify({
    Date: currentDate,
    Time: currentTime,
    Location: location,
    UserText: qrText,
  });
  const qrCodeSvg = QRCODE({ value: qrCodeData });
  const handlePrint = async () => {
    try {
      const html = `
        <html>
          <head>
            <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
          </head>
          <h1> Qr Code</h1>
          <body style="text-align: center;">
            ${qrCodeSvg} 
          </body>
        </html>
      `;
      console.log(html);
      await Print.printAsync({
        html,
      });
    } catch (error) {
      console.error("Printing error:", error);
    }
  };
  return (
    <View style={styles.container}>
      <View>
        <Text style={styles.header}>Qr Code</Text>
        <QRCODE value={qrCodeData} />
        <TouchableOpacity
          style={styles.printButton}
          onPress={handlePrint}
          activeOpacity={0.6}
        >
          <Text>Print</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "row",
    justifyContent: "center",
    alignItems: "center",
  },
  header: {
    alignSelf: "center",
    fontSize: 25,
    fontWeight: "bold",
    marginBottom: 16,
  },
  printButton: {
    alignItems: "center",
    backgroundColor: "#DEB887",
    padding: 10,
    borderRadius: 8,
    marginTop: 25,
  },
});

export default QRscreen;`

QRCode component:

import QRCode from "react-native-qrcode-svg";


const QRCODE = ({ value, getRef }) => {
  return <QRCode value={value} size={200} getRef={getRef} />;
  
};

export default QRCODE;`


Solution

  • One way to accomplish this is to utilise img tag and data url.

    const svg = useRef(null);
    const [dataUrl, setDataUrl] = useState(null);
    
    const handlePrint = async () => {
      const html = `<img src="data:image/jpeg;base64,${dataUrl}"/>`;
      await Print.printAsync({
        html,
      });
    };
    
    useEffect(() => {
      const getDataURL = () => {
        svg.current.toDataURL(setDataUrl);
      };
      if (svg.current != null) {
        getDataURL();
      }
    }, [svg]);
    
    return (
      <View>
        <QRCode value="Hello" size={200} getRef={(c) => (svg.current = c)} />
        <Button
          title="Print"
          onPress={handlePrint} />
      </View>
    );