wojtekmaj / react-pdf

Display PDFs in your React app as easily as if they were images.
https://projects.wojtekmaj.pl/react-pdf
MIT License
9.58k stars 898 forks source link

Pdf pages rendering twice (once with correct formatting and then twice with just text) #1693

Closed nathanvale closed 11 months ago

nathanvale commented 11 months ago

Before you start - checklist

Description

Screenshot 2024-01-09 at 1 32 19 pm Screenshot 2024-01-09 at 1 32 28 pm

Steps to reproduce

import { useCallback, useState } from 'react';
import { useResizeObserver } from '@wojtekmaj/react-hooks';
import { pdfjs, Document, Page } from 'react-pdf';
import {
  Button,
  Dialog,
  DialogContent,
  DialogActions,
  Typography,
} from 'zero-develop-component-library';

import type { PDFDocumentProxy } from 'pdfjs-dist';

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  'pdfjs-dist/build/pdf.worker.min.js',
  import.meta.url,
).toString();

const options = {
  cMapUrl: '/cmaps/',
  standardFontDataUrl: '/standard_fonts/',
};

const resizeObserverOptions = {};

const maxWidth = 800;

type PDFFile = string | File | null;

export interface SampleProps {
  onClose: () => void;
  open: boolean;
}

export const TermsAndConditionsModal = ({ onClose, open }: SampleProps) => {
  const [file, setFile] = useState<PDFFile>('./static/dummy_T_C.pdf');
  const [numPages, setNumPages] = useState<number>();
  const [containerRef, setContainerRef] = useState<HTMLElement | null>(null);
  const [containerWidth, setContainerWidth] = useState<number>();

  const onResize = useCallback<ResizeObserverCallback>((entries) => {
    const [entry] = entries;

    if (entry) {
      setContainerWidth(entry.contentRect.width);
    }
  }, []);

  useResizeObserver(containerRef, resizeObserverOptions, onResize);

  function onDocumentLoadSuccess({
    numPages: nextNumPages,
  }: PDFDocumentProxy): void {
    setNumPages(nextNumPages);
  }

  function downloadPdf() {
    window.location.href = file as any;
  }

  return (
    <Dialog
      data-id="terms-and-conditions-confirm-modal"
      disableEscapeKeyDown
      open={open}
      onClose={onClose}
      maxWidth="xs"
    >
      <DialogContent sx={{ padding: '24px 16px 16px 16px' }}>
        <Typography sx={{ pb: '16px' }} variant="body2">
          Please tick the checkbox to agree to our Terms and Conditions before
          proceeding.
        </Typography>
        <DialogActions sx={{ justifyContent: 'center', padding: '0' }}>
          <Button onClick={onClose} variant="contained">
            Close
          </Button>
        </DialogActions>
        <div ref={setContainerRef}>
          <Document
            file={file}
            onLoadSuccess={onDocumentLoadSuccess}
            options={options}
          >
            {Array.from(new Array(numPages), (el, index) => (
              <Page
                key={`page_${index + 1}`}
                pageNumber={index + 1}
                width={
                  containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth
                }
              />
            ))}
          </Document>
        </div>
      </DialogContent>
    </Dialog>
  );
};
{
  "name": "zero-develop-frontend-desa",
  "description": "Zero dESA page",
  "author": "Origin Jindabyne",
  "version": "0.0.1",
  "private": true,
  "homepage": "/desa",
  "proxy": "http://localhost:3002",
  "resolutions": {
    "semver": "7.5.2",
    "webpack": "5.76.0",
    "@babel/traverse": "7.23.2",
    "tough-cookie": "4.1.3",
    "apollo-server-core": "https://nexus.jindabyne.em.originenergy.com.au/repository/npm-proxy/apollo-server-core/-/apollo-server-core-2.26.2.tgz#5391bb93654194a5d6b83cf1855f229c94d5b3b1",
    "core-js": "3.28.0",
    "requestretry": "7.1.0",
    "busboy": "1.6.0",
    "canvas": "link:./node_modules/.cache/null"
  },
  "dependencies": {
    "@emotion/react": "^11.10.5",
    "@emotion/styled": "^11.10.5",
    "@local/zero-contract-desa": "file:../contract/build/ts",
    "@material-ui/icons": "^4.11.3",
    "@mui/icons-material": "^5.10.16",
    "@mui/material": "^5.11.9",
    "@mui/x-date-pickers": "^5.0.11",
    "@origin-digital/ods-core": "^1.7.0",
    "@types/node-fetch": "^2.6.1",
    "history": "^4.10.1",
    "lodash": "^4.17.21",
    "luxon": "^3.3.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "5.0.1",
    "zero-develop-component-library": "^0.3.31",
    "@wojtekmaj/react-hooks": "^1.18.0",
    "react-pdf": "latest"
  },
  "scripts": {
    "start": "ENV=local ts-node --project ./tsconfig.dev.json ./devTools/dev-server.ts",
    "start:contained": "ENV=contained ts-node --project ./tsconfig.dev.json ./devTools/dev-server.ts",
    "start:dev": "ENV=local react-app-rewired start",
    "test": "react-scripts test",
    "test:ci": "react-scripts test --ci --watchAll=false --coverage src --reporters=default --reporters=jest-junit --detectOpenHandles --silent=true --transformIgnorePatterns 'node_modules/(?!(zero-develop-component-library)/)'",
    "build": "react-app-rewired build",
    "build:ci": "ENV=local react-app-rewired build",
    "stub": "digital-graphql-stub",
    "stub:mocks": "ts-node --project ./tsconfig.dev.json ./devTools/load-mocks.ts",
    "prettier": "prettier --write \"./{src,test,devTools,functional-tests}/**/*.{ts,tsx,js}\"",
    "format": "yarn prettier",
    "format:check": "yarn prettier -l",
    "lint": "tslint 'src/**/*.ts?(x)'",
    "eject": "react-scripts eject",
    "type:check": "tsc --noEmit"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@origin-digital/digital-graphql-stub": "^1.11.0",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^12.1.5",
    "@testing-library/react-hooks": "^8.0.1",
    "@testing-library/user-event": "^14.4.3",
    "@types/history": "^4.7.8",
    "@types/jest": "^28.1.6",
    "@types/luxon": "^3.3.0",
    "@types/node": "^18.7.1",
    "@types/react": "^18.0.17",
    "@types/react-dom": "^18.0.6",
    "@types/react-router-dom": "^5.3.3",
    "@types/styled-components": "^5.1.26",
    "axios": "^0.26.1",
    "customize-cra": "^1.0.0",
    "husky": "4",
    "jest-junit": "^14.0.0",
    "ls": "^0.2.1",
    "prettier": "^2.7.1",
    "react": "^17.0.2",
    "react-app-rewired": "^2.1.8",
    "react-dom": "^17.0.2",
    "react-select": "5.2.2",
    "react-test-renderer": "^17.0.1",
    "rewire": "^5.0.0",
    "start-server-and-test": "^1.12.1",
    "styled-components": "5.2.1",
    "ts-node": "^10.8.0",
    "tslint": "^6.1.3",
    "tslint-config-prettier": "^1.18.0",
    "typescript": "^4.0.3"
  },
  "husky": {
    "hooks": {
      "pre-commit": "yarn type:check && yarn format:check && yarn lint && yarn test:ci",
      "post-merge": "make -C ../ prepare"
    }
  },
  "jest": {
    "moduleNameMapper": {
      "\\worker-loader": "<rootDir>/testing-utils/__mocks__/workerMock.js"
    },
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,ts,tsx}",
      "!<rootDir>/node_modules/",
      "!<rootDir>/src/index.tsx",
      "!<rootDir>/src/Constants/*",
      "!<rootDir>/src/Contracts/**/*",
      "!<rootDir>/src/**/*.Styles.{ts,tsx}",
      "!<rootDir>/src/types/*",
      "!**/*.d.ts"
    ],
    "coverageThreshold": {
      "global": {
        "branches": 5,
        "functions": 4,
        "lines": 5,
        "statements": 5
      }
    },
    "transformIgnorePatterns": [
      "node_modules/(?!@ngrx|(?!deck.gl)|ng-dynamic)",
      "node_modules/(?!(zero-develop-component-library)/)"
    ]
  }
}

Expected behavior

Pdf pages should render correctly with no additional pages with just text

Actual behavior

Pdf pages render incorrectly with additional pages with just text

Additional information

No response

Environment

CSWITH89 commented 10 months ago

I am also encountering this issue. Any update?

mwanago commented 9 months ago

@CSWITH89 Try using renderTextLayer={false} renderAnnotationLayer={false}

wojtekmaj commented 9 months ago

Duplicate of #1292

wojtekmaj commented 9 months ago

@mwanago This way you're removing an important accessibility feature. I would advise against it in most cases.

franshuyadav commented 2 months ago

Late to the thread, but on adding renderAnnotationLayer={false} or importing the annotation css layer, the scale attribute of Page stops working. Anyone found a workaround for that?