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.11k stars 867 forks source link

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

Closed nathanvale closed 6 months ago

nathanvale commented 6 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 6 months ago

I am also encountering this issue. Any update?

mwanago commented 5 months ago

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

wojtekmaj commented 5 months ago

Duplicate of #1292

wojtekmaj commented 5 months ago

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