How to print a nested component correctly with react-to-print

164 Views Asked by At

This is my main form component to print:

import { Fragment, useRef } from "react";
import FormDataPrint from "../Printer/FormDataPrint";
import ReactToPrint from "react-to-print";
import { Card, Button } from "reactstrap";
import { Printer } from "react-feather";

const FormData = ({ data }) => {
  const formDataPrintRef = useRef();

  const handlePrint = () => {
    const formDataPrint = formDataPrintRef.current;
    if (formDataPrint) {
      formDataPrint.handlePrint();
    }
  };

  return (
    <Fragment>
      {/* This is Form Area (Input etc.) */}
      <Card>
        <div className="d-flex justify-content-end mt-1">
          <ReactToPrint
            trigger={() => (
              <Button
                className="ms-1 text-center"
                outline
                color="primary"
                onClick={handlePrint}
              >
                <Printer style={{ marginRight: "5px" }} size={20} />
                <span>Print</span>
              </Button>
            )}
            content={() => formDataPrintRef.current}
          />
          <div style={{ display: "none" }}>
            <FormDataPrint ref={formDataPrintRef} data={data} />
          </div>
        </div>
      </Card>
    </Fragment>
  );
};

export default FormData;

This is the child component FormDataPrint:

import React, { forwardRef } from "react";

const FormDataPrint = forwardRef((props, ref) => {
  const { data } = props;

  return <div ref={ref}>Print just this</div>;
});

export default FormDataPrint;

Here I just want to create a special structure for the content of the child component and print the incoming data (for example: name, surname). But when the print page is opened, although the div content is empty, it comes as two pages and I can only change the colors when styling into the div. I can only give padding, margin with inline style into the div in the child component. I tried with css, I could not understand that only the color changed.

Most of info I found was printing out the whole page it was on.

1

There are 1 best solutions below

1
On

FormDataPrint.jsx:

import React, { forwardRef } from "react";
import { Card } from "reactstrap";

const FormDataPrint = forwardRef((props, ref) => {
  const { data } = props;

  const divStyle = {
    color: "blue", // Example color change
    padding: "10px", // Example padding
    margin: "5px", // Example margin
  };

  return (
    <Card style={divStyle} ref={ref}>
      <p>Name: {data.name}</p>
      <p>Surname: {data.surname}</p>
    </Card>
  );
});

export default FormDataPrint;

FormData.jsx:

import { Fragment, useRef } from "react";
import FormDataPrint from "../Printer/FormDataPrint";
import ReactToPrint from "react-to-print";
import { Card, Button } from "reactstrap";
import { Printer } from "react-feather";

const FormData = ({ data }) => {
  const formDataPrintRef = useRef();

  const handlePrint = () => {
    const formDataPrint = formDataPrintRef.current;
    if (formDataPrint) {
      formDataPrint.handlePrint();
    }
  };

  return (
    <Fragment>
      {/* This is Form Area (Input etc.) */}
      <Card>
        <div className="d-flex justify-content-end mt-1">
          <ReactToPrint
            trigger={() => (
              <Button
                className="ms-1 text-center"
                outline
                color="primary"
                onClick={handlePrint}
              >
                <Printer style={{ marginRight: "5px" }} size={20} />
                <span>Print</span>
              </Button>
            )}
            content={() => formDataPrintRef.current}
          />
          <div style={{ display: "none" }}>
            <FormDataPrint ref={formDataPrintRef} data={data} />
          </div>
        </div>
      </Card>
    </Fragment>
  );
};

export default FormData;

Now, in this modified FormDataPrint component, I've applied styles directly to the Card component using the divStyle object. You can customize these styles according to your needs.