Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDFViewer does not render until reloaded #3090

Open
nimeshmaharjan1 opened this issue Feb 20, 2025 · 3 comments
Open

PDFViewer does not render until reloaded #3090

nimeshmaharjan1 opened this issue Feb 20, 2025 · 3 comments

Comments

@nimeshmaharjan1
Copy link

nimeshmaharjan1 commented Feb 20, 2025

Describe the bug

  • I have used the to display the PDF in the web app but on the first render the PDFViewer is not shown.

  • I have to reload sometimes even multiple times

  • I have a condition that checks if the data from the API has arrived before rendering the DOM so I dont think its because of that.

  • If there are any loading states that I am missing do let me know

  • Below is the code snippet

	if (
		!queryResult.data ||
		queryResult.isLoading ||
		!userData ||
		isLoading ||
		!window
	)
		return <LoadingScreen />;

	return (
		<div className="w-screen min-h-screen bg-white grid text-black">
			<Container maxWidth="md" className="py-6 px-0 h-full">
				

				<PDFViewer height={600} width={"100%"}>
					<ReportPDF
						pdfTitle={props.reportTitle}
						reportTitle={props.reportTitle}
						data={parsedData}
						tableHead={TABLE_HEAD}
						user={{
							address: userData.address ? CombineAddress(userData.address) : "",
							avatar: userData.avatar,
							name: ConstructFullName(
								userData.firstName,
								userData.middleName,
								userData.lastName
							),
							role: role.key,
						}}
						companyInfo={{
							name:
								role.key === "superadmin"
									? "ABC"
									: (role.role?.companyName ?? ""),
							logo:
								(role.key === "superadmin"
									? LOGOS.MMD
									: role.role?.companyLogo) ?? LOGOS.MMD,
						}}
					/>
				</PDFViewer>
			</Container>
		</div>
	);

Screenshots

First Render =>

Image

After Reloading =>

Image

Desktop (please complete the following information):

  • OS: Mac, Windows, Linux
  • Browser Chrome
  • React-pdf version 7.7.3
  • @react-pdf/renderer": "^3.4.5
@Souravkkt0404
Copy link

It looks like your PDFViewer component isn't rendering properly on the first load, requiring multiple reloads. Since you already have a condition ensuring data availability before rendering, the issue might be related to:

  1. Delayed API Response / Query Inconsistencies

    • Even though queryResult.isLoading is checked, sometimes React Query updates state asynchronously, and queryResult.data might still be undefined momentarily.
    • Try adding a console log to verify the state before rendering:
      console.log("Query Result:", queryResult);
      console.log("User Data:", userData);
      console.log("Window:", typeof window !== "undefined");
  2. window Check & SSR Issues

    • If you're using Next.js or any SSR framework, the window object is only available on the client side.
    • Try ensuring that PDFViewer is rendered only on the client:
      import dynamic from "next/dynamic";
      
      const PDFViewer = dynamic(() => import("@react-pdf/renderer").then((mod) => mod.PDFViewer), { ssr: false });
  3. Force Re-render on Data Change

    • The PDFViewer might not be updating properly when data arrives.
    • Try forcing a re-render using useEffect and useState:
      const [readyToRender, setReadyToRender] = useState(false);
      
      useEffect(() => {
        if (queryResult.data && userData) {
          setReadyToRender(true);
        }
      }, [queryResult.data, userData]);
      
      if (!readyToRender) return <LoadingScreen />;
  4. Check for ReportPDF Issues

    • Ensure parsedData, TABLE_HEAD, and user are not undefined before passing them to ReportPDF.
    • Wrap ReportPDF inside a useMemo hook to avoid unnecessary re-renders:
      const memoizedPDF = useMemo(() => (
        <ReportPDF
          pdfTitle={props.reportTitle}
          reportTitle={props.reportTitle}
          data={parsedData}
          tableHead={TABLE_HEAD}
          user={{
            address: userData.address ? CombineAddress(userData.address) : "",
            avatar: userData.avatar,
            name: ConstructFullName(
              userData.firstName,
              userData.middleName,
              userData.lastName
            ),
            role: role.key,
          }}
          companyInfo={{
            name:
              role.key === "superadmin"
                ? "ABC"
                : (role.role?.companyName ?? ""),
            logo:
              (role.key === "superadmin"
                ? LOGOS.MMD
                : role.role?.companyLogo) ?? LOGOS.MMD,
          }}
        />
      ), [parsedData, userData, role, props.reportTitle]);
      
      return (
        <PDFViewer height={600} width={"100%"}>
          {memoizedPDF}
        </PDFViewer>
      );

Final Steps to Debug:

  • Check console logs to verify state changes.
  • Use useEffect to track queryResult.data updates.
  • Try delaying rendering slightly using setTimeout(() => setReady(true), 500);
  • Ensure that React-PDF dependencies are correctly installed.

1 similar comment
@Souravkkt0404
Copy link

It looks like your PDFViewer component isn't rendering properly on the first load, requiring multiple reloads. Since you already have a condition ensuring data availability before rendering, the issue might be related to:

  1. Delayed API Response / Query Inconsistencies

    • Even though queryResult.isLoading is checked, sometimes React Query updates state asynchronously, and queryResult.data might still be undefined momentarily.
    • Try adding a console log to verify the state before rendering:
      console.log("Query Result:", queryResult);
      console.log("User Data:", userData);
      console.log("Window:", typeof window !== "undefined");
  2. window Check & SSR Issues

    • If you're using Next.js or any SSR framework, the window object is only available on the client side.
    • Try ensuring that PDFViewer is rendered only on the client:
      import dynamic from "next/dynamic";
      
      const PDFViewer = dynamic(() => import("@react-pdf/renderer").then((mod) => mod.PDFViewer), { ssr: false });
  3. Force Re-render on Data Change

    • The PDFViewer might not be updating properly when data arrives.
    • Try forcing a re-render using useEffect and useState:
      const [readyToRender, setReadyToRender] = useState(false);
      
      useEffect(() => {
        if (queryResult.data && userData) {
          setReadyToRender(true);
        }
      }, [queryResult.data, userData]);
      
      if (!readyToRender) return <LoadingScreen />;
  4. Check for ReportPDF Issues

    • Ensure parsedData, TABLE_HEAD, and user are not undefined before passing them to ReportPDF.
    • Wrap ReportPDF inside a useMemo hook to avoid unnecessary re-renders:
      const memoizedPDF = useMemo(() => (
        <ReportPDF
          pdfTitle={props.reportTitle}
          reportTitle={props.reportTitle}
          data={parsedData}
          tableHead={TABLE_HEAD}
          user={{
            address: userData.address ? CombineAddress(userData.address) : "",
            avatar: userData.avatar,
            name: ConstructFullName(
              userData.firstName,
              userData.middleName,
              userData.lastName
            ),
            role: role.key,
          }}
          companyInfo={{
            name:
              role.key === "superadmin"
                ? "ABC"
                : (role.role?.companyName ?? ""),
            logo:
              (role.key === "superadmin"
                ? LOGOS.MMD
                : role.role?.companyLogo) ?? LOGOS.MMD,
          }}
        />
      ), [parsedData, userData, role, props.reportTitle]);
      
      return (
        <PDFViewer height={600} width={"100%"}>
          {memoizedPDF}
        </PDFViewer>
      );

Final Steps to Debug:

  • Check console logs to verify state changes.
  • Use useEffect to track queryResult.data updates.
  • Try delaying rendering slightly using setTimeout(() => setReady(true), 500);
  • Ensure that React-PDF dependencies are correctly installed.

@nimeshmaharjan1
Copy link
Author

It looks like your PDFViewer component isn't rendering properly on the first load, requiring multiple reloads. Since you already have a condition ensuring data availability before rendering, the issue might be related to:

  1. Delayed API Response / Query Inconsistencies

    • Even though queryResult.isLoading is checked, sometimes React Query updates state asynchronously, and queryResult.data might still be undefined momentarily.
    • Try adding a console log to verify the state before rendering:
      console.log("Query Result:", queryResult);
      console.log("User Data:", userData);
      console.log("Window:", typeof window !== "undefined");
  2. window Check & SSR Issues

    • If you're using Next.js or any SSR framework, the window object is only available on the client side.

    • Try ensuring that PDFViewer is rendered only on the client:
      import dynamic from "next/dynamic";

      const PDFViewer = dynamic(() => import("@react-pdf/renderer").then((mod) => mod.PDFViewer), { ssr: false });

  3. Force Re-render on Data Change

    • The PDFViewer might not be updating properly when data arrives.

    • Try forcing a re-render using useEffect and useState:
      const [readyToRender, setReadyToRender] = useState(false);

      useEffect(() => {
      if (queryResult.data && userData) {
      setReadyToRender(true);
      }
      }, [queryResult.data, userData]);

      if (!readyToRender) return ;

  4. Check for ReportPDF Issues

    • Ensure parsedData, TABLE_HEAD, and user are not undefined before passing them to ReportPDF.

    • Wrap ReportPDF inside a useMemo hook to avoid unnecessary re-renders:
      const memoizedPDF = useMemo(() => (
      <ReportPDF
      pdfTitle={props.reportTitle}
      reportTitle={props.reportTitle}
      data={parsedData}
      tableHead={TABLE_HEAD}
      user={{
      address: userData.address ? CombineAddress(userData.address) : "",
      avatar: userData.avatar,
      name: ConstructFullName(
      userData.firstName,
      userData.middleName,
      userData.lastName
      ),
      role: role.key,
      }}
      companyInfo={{
      name:
      role.key === "superadmin"
      ? "ABC"
      : (role.role?.companyName ?? ""),
      logo:
      (role.key === "superadmin"
      ? LOGOS.MMD
      : role.role?.companyLogo) ?? LOGOS.MMD,
      }}
      />
      ), [parsedData, userData, role, props.reportTitle]);

      return (
      <PDFViewer height={600} width={"100%"}>
      {memoizedPDF}

      );

Final Steps to Debug:

  • Check console logs to verify state changes.
  • Use useEffect to track queryResult.data updates.
  • Try delaying rendering slightly using setTimeout(() => setReady(true), 500);
  • Ensure that React-PDF dependencies are correctly installed.

Thank you very much for the detailed reply so basically what I did was the loading state that we get from the PDFDownloadLink component i stored it in a local state and used it as a loading indicator for the pdf as well which solved the issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants