0

I would need smooth scrolling down to component with generated pdf. But it looks like that first is scrolled to view and then component is mounted. How can I set waiting to component is displayed and then scroll to view this component? When I click to button, the pdf will start to generate. After generating this pdf, I would like scroll to view this PDFViewer.

My solution does not work. 'await' has no effect on the type of this expression. OR Object is possibly 'null'.

I use reactjs 17.0.2, react-pdf/renderer 3.0.1, typescript.

Code:

import { PDFViewer } from "@react-pdf/renderer";

export const Print: NextPage = () => {
  const [pdfGenerationEnabled, setPdfGenerationEnabled] = useState<boolean>(false);

  const generatePDFAndView = async () => {
    setPdfGenerationEnabled(true);
    await document.getElementById("generated-pdf-view")?.scrollIntoView({ behavior: "smooth" });
  }

  return (
    <DownloadAndPrint>
      <h2>Generating PDF</h2>
      <p>
        Some long text
        Some long text
        Some long text
        .
        .
        .
      </p>
      <Button
        className="btn-generate-pdf"
        onClick={() => { generatePDFAndView() }}
      >
        Vygenerovať pdf súbory
      </Button>
      {pdfGenerationEnabled
        ? 
          <>
            <div id="generated-pdf-view" className="viewer-styled">
              <PDFViewer showToolbar={true} style={{ height: "45vh", width: "100%" }}>
                <ComponentPrint 
                  data={data}
                />
              </PDFViewer>
            </div>
          </>
        : ""
      }
    </DownloadAndPrint>
  );
};

EDITED: After added delay, it's works. After 3 seconds smooth scrolled to the pdf viewer. But I don't know how many seconds it should waiting? Sometimes generated pdf has 3 pages, sometimes 300 pages. According to the data.

const delay = (n) => new Promise(r => setTimeout(r, n*1000));

const generatePDFAndView = async () => {
  setPdfGenerationEnabled(true);
  await delay(3.0);  // waiting 3s
  document.getElementById("generated-pdf-view")?.scrollIntoView({ behavior: "smooth" });
}
Elo
  • 226
  • 5
  • 19
  • Let's try to think without pdf. Page is rendered. `
    ` does not exist on rendered page. User click on button, then useState pdfGenerationEnabled is set to true. Then is called `scrollIntoView()` to non-existent `
    ` and then is displayed `
    `. How to do it the other way around? 1. to display the
    2. to call `scrollIntoView()`
    – Elo Nov 10 '22 at 10:24
  • In browser it's iframe. `
    `
    – Elo Nov 10 '22 at 11:04
  • I edited question. After added delay, it's works. But I don't know how many seconds it should waiting? – Elo Nov 10 '22 at 11:14
  • I tried with toolbar id: `document.getElementById("toolbar")?.scrollIntoView({ behavior: "smooth" });` It isn't works also with `delay()`. – Elo Nov 10 '22 at 11:21

1 Answers1

0

My solution with delay and calculation time to wait according to the data. Maybe somebody it helps.

import { PDFViewer } from "@react-pdf/renderer";

export const Print: NextPage = () => {
  const [pdfGenerationEnabled, setPdfGenerationEnabled] = useState<boolean>(false);
  const itemsPerPage = 5;

  const calculateTimeToDisplayPdfViewer = () => {
    const numberOfItems = data?.items?.length;
    if (numberOfItems > 0 && itemsPerPage > 0) {
      let time = (numberOfItems / itemsPerPage) / 5;  // 1 page = 1/5s = 0.20s
      time = parseFloat(time.toFixed(2));
      console.log("Waiting " + time + "s.");
      return time;
    } else {
      return 2.0;
    }
  }

  const delay = (n) => new Promise( r => setTimeout(r, n*1000));  // waiting in seconds

  const generatePDFAndView = async () => {
    setPdfGenerationEnabled(true);
    await delay(calculateTimeToDisplayPdfViewer());
    document.getElementById("generated-pdf-view")?.scrollIntoView({ behavior: "smooth" });
  }

  return (
    <DownloadAndPrint>
      <h2>Generating PDF</h2>
      <p>
        Some long text
        Some long text
        Some long text
        .
        .
        .
      </p>
      <Button
        className="btn-generate-pdf"
        onClick={() => { generatePDFAndView() }}
      >
        Vygenerovať pdf súbory
      </Button>
      {pdfGenerationEnabled
        ? 
          <>
            <div id="generated-pdf-view" className="viewer-styled">
              <PDFViewer showToolbar={true} style={{ height: "45vh", width: "100%" }}>
                <ComponentPrint 
                  data={data}
                />
              </PDFViewer>
            </div>
          </>
        : ""
      }
    </DownloadAndPrint>
  );
};
Elo
  • 226
  • 5
  • 19