diegomura / react-pdf

đź“„ Create PDF files using React
https://react-pdf.org
MIT License
14.64k stars 1.16k forks source link

Library conflicts with libraries that uses `useSyncExternalStore` React 18 API #2263

Open maxsbelt opened 1 year ago

maxsbelt commented 1 year ago

Describe the bug I tried to add @react-pdf/renderer library to my project that uses import "@preact/signals-react" and received the next error:

dispatcher.useSyncExternalStore is not a function

To Reproduce

  1. Generate react project with CRA or VITE
  2. Add @react-pdf/renderer and @preact/signals-react dependencies
  3. Add next code
  4. Observe error
import "@preact/signals-react";
import { createRoot } from "react-dom/client";
import { PDFViewer, Document, View, Text, Page } from "@react-pdf/renderer";

function SeparateComponent() {
  return <Text>Hello, World!</Text>;
}

createRoot(document.getElementById("root")).render(
  <PDFViewer>
    <Document>
      <Page>
        <View>
          <Text>Hello, World!</Text>
          {/* if you comment next line everything will work properly */}
          <SeparateComponent />
        </View>
      </Page>
    </Document>
  </PDFViewer>
);

Link to codesandbox: https://codesandbox.io/s/heuristic-worker-o55gp4?file=/src/index.js:0-542

Expected behavior Should work properly

UPDATE: I was able to solve this problem from my side. My actions:

It still displays an error in the browser console but the PDF view itself works.

DarkSmile92 commented 1 year ago

@maxsbelt I tried your approach but somehow it did not solve my issue.

TypeError: dispatcher.useSyncExternalStore is not a function The overrides you posted cannot resolve $scheduler and $react-reconciler so I tried it with latest.

...
"dependencies": {
    "@datadog/browser-logs": "^4.19.1",
    "@next-auth/prisma-adapter": "^1.0.5",
    "@prisma/client": "^4.11.0",
    "@react-pdf/renderer": "^3.1.9",
    "@reduxjs/toolkit": "^1.9.3",
    "aws-sdk": "^2.1344.0",
    "axios": "^1.3.4",
    "base64-stream": "^1.0.0",
    "bcrypt": "^5.0.0",
    "busboy": "^1.6.0",
    "concat-stream": "^2.0.0",
    "crypto": "^1.0.1",
    "crypto-browserify": "^3.12.0",
    "date-fns": "^2.29.3",
    "dotenv": "^16.0.3",
    "events-polyfill": "^2.1.2",
    "file-saver": "^2.0.5",
    "formik": "^2.2.9",
    "hat": "^0.0.3",
    "lodash.pick": "^4.4.0",
    "lodash.tostring": "^4.1.4",
    "mailersend": "^2.0.5",
    "md5": "^2.3.0",
    "moment": "^2.29.4",
    "multiparty": "^4.2.3",
    "next": "^13.2.4",
    "next-auth": "^4.20.1",
    "next-connect": "^0.13.0",
    "next-dark-mode": "^3.0.0",
    "next-i18next": "^12.0.0",
    "next-plausible": "^3.7.2",
    "nodemailer": "^6.9.1",
    "qrcode.react": "^3.1.0",
    "rc-tree": "^5.7.3",
    "react": "^18.2.0",
    "react-calendly": "^4.1.1",
    "react-color": "^2.19.3",
    "react-csv": "^2.2.2",
    "react-csv-reader": "^4.0.0",
    "react-currency-format": "github:mohitgupta8888/react-currency-format#4f365ec5005e23451a3b95da1a209b0025622b8d",
    "react-datepicker": "^4.10.0",
    "react-dnd": "^16.0.1",
    "react-dnd-html5-backend": "^16.0.1",
    "react-dom": "^18.2.0",
    "react-hot-keys": "^2.7.2",
    "react-hot-toast": "^2.4.0",
    "react-icons": "^4.8.0",
    "react-player": "^2.12.0",
    "react-redux": "^8.0.5",
    "react-semantic-ui-datepickers": "^2.17.2",
    "react-sortablejs": "^6.1.4",
    "react-transition-group": "^4.4.5",
    "recharts": "^2.5.0",
    "semantic-ui-css": "^2.5.0",
    "semantic-ui-react": "^2.1.4",
    "sortablejs": "^1.15.0",
    "ua-parser-js": "^1.0.34",
    "uuid": "^9.0.0",
    "yup": "^1.0.2",
    "zxcvbn": "^4.4.2"
  },
  "devDependencies": {
    "@next/bundle-analyzer": "^13.2.4",
    "@playwright/test": "^1.32.1",
    "@types/bcrypt": "^5.0.0",
    "@types/file-saver": "^2.0.5",
    "@types/lodash.tostring": "^4.1.7",
    "@types/node": "^18.15.10",
    "@types/nodemailer": "^6.4.7",
    "@types/react": "^18.0.30",
    "@types/react-color": "^3.0.6",
    "@types/react-csv": "^1.1.3",
    "@types/react-currency-format": "^1.0.0",
    "@types/react-datepicker": "^4.10.0",
    "@types/react-dom": "^18.0.11",
    "@types/react-transition-group": "^4.4.5",
    "@types/recharts": "^1.8.24",
    "@types/sortablejs": "^1.15.1",
    "@types/ua-parser-js": "^0.7.36",
    "@types/zxcvbn": "^4.4.1",
    "@typescript-eslint/eslint-plugin": "^5.57.0",
    "@typescript-eslint/parser": "^5.57.0",
    "cz-conventional-changelog": "^3.3.0",
    "dotenv-cli": "^7.1.0",
    "eslint": "^8.36.0",
    "eslint-config-prettier": "^8.8.0",
    "eslint-formatter-git-log": "^0.6.4",
    "eslint-formatter-mo": "^1.2.0",
    "eslint-plugin-jsx-a11y": "^6.7.1",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-security": "^1.7.1",
    "eslint-plugin-simple-import-sort": "^10.0.0",
    "eslint-plugin-sonarjs": "^0.19.0",
    "eslint-plugin-unicorn": "^46.0.0",
    "file-loader": "^6.2.0",
    "husky": "^8.0.3",
    "lint-staged": "^13.2.0",
    "prettier": "^2.8.7",
    "prisma": "^4.11.0",
    "standard-version": "^9.5.0",
    "stylelint": "^13.0.0",
    "stylelint-config-idiomatic-order": "^9.0.0",
    "stylelint-config-prettier": "^9.0.5",
    "stylelint-config-sass-guidelines": "^8.0.0",
    "stylelint-config-standard": "^22.0.0",
    "stylelint-prettier": "^1.2.0",
    "stylelint-scss": "^3.21.0",
    "typescript": "^5.0.2",
    "url-loader": "^4.1.1",
    "webpack": "^5.76.3"
  },
  "overrides": {
    "@react-pdf/renderer": {
      "react": "$react",
      "react-reconciler": "latest",
      "scheduler": "latest"
    }
  }

Do you maybe have a hint how else to solve it? :)

Here is the full error:

TypeError: dispatcher.useSyncExternalStore is not a function

index.tsx?32c0:114 Uncaught (in promise) TypeError: dispatcher.useSyncExternalStore is not a function
    at Object.useSyncExternalStore (react.development.js?1b7e:1676:1)
    at LoadableComponent (loadable.js?5107:86:38)
    at Jd (react-pdf.browser.es.js?3b48:1113:1)
    at qe (react-pdf.browser.es.js?3b48:1571:1)
    at ig (react-pdf.browser.es.js?3b48:3435:1)
    at hg (react-pdf.browser.es.js?3b48:2829:1)
    at bg (react-pdf.browser.es.js?3b48:2823:23)
    at Of (react-pdf.browser.es.js?3b48:2625:1)
    at eval (react-pdf.browser.es.js?3b48:472:1)
    at unstable_runWithPriority (scheduler.development.js?bcd2:818:1)
    at hc (react-pdf.browser.es.js?3b48:445:1)
    at kc (react-pdf.browser.es.js?3b48:469:1)
    at F (react-pdf.browser.es.js?3b48:461:1)
    at Wc (react-pdf.browser.es.js?3b48:2461:1)
    at Object.updateContainer (react-pdf.browser.es.js?3b48:3747:1)
    at updateContainer (react-pdf.browser.es.js?3b48:4069:1)
    at pdf (react-pdf.browser.es.js?3b48:4071:1)
    at downloadPdf (index.tsx?32c0:112:27)
    at Object.onClick (index.tsx?32c0:264:42)
    at apply (_apply.js?c902:15:1)
    at baseInvoke (_baseInvoke.js?9e4e:21:42)
    at apply (_apply.js?c902:16:1)
    at eval (_overRest.js?bb93:32:17)
    at Button._this.handleClick (Button.js?7a7c:63:14)
    at HTMLUnknownElement.callCallback (react-dom.development.js?ac89:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?ac89:4213:1)
    at invokeGuardedCallback (react-dom.development.js?ac89:4277:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?ac89:4291:1)
    at executeDispatch (react-dom.development.js?ac89:9041:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js?ac89:9073:1)
    at processDispatchQueue (react-dom.development.js?ac89:9086:1)
    at dispatchEventsForPlugins (react-dom.development.js?ac89:9097:1)
    at eval (react-dom.development.js?ac89:9288:1)
    at batchedUpdates$1 (react-dom.development.js?ac89:26140:1)
    at batchedUpdates (react-dom.development.js?ac89:3991:1)
    at dispatchEventForPluginEventSystem (react-dom.development.js?ac89:9287:1)
    at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (react-dom.development.js?ac89:6465:1)
    at dispatchEvent (react-dom.development.js?ac89:6457:1)
    at dispatchDiscreteEvent (react-dom.development.js?ac89:6430:1)
DarkSmile92 commented 1 year ago

It was actually the suspense loading issue.

I was using next/dynamic to dynamically load the PDF document component. Directly importing it solved the issue together with your overrides solution :)

It hit me while reading this: https://github.com/reduxjs/react-redux/issues/1977

dev0T commented 1 year ago

I am having the same issue. I am using Zustand to create a store and attempting to access this store inside my React PDF components to dynamic render its contents.

dev0T commented 1 year ago

My solution for this was to access the Zustand store in the component that renders PDFViewer and pass the needed values to the component that renders Document as props. If the PDF is too complex, it might be helpful to create a context

julio-benavente commented 6 months ago

I was using react-redux and NextJS. I had to downgrade to version ^7.0.0 (npm i react-redux@^7.0.0).

didemkkaslan commented 3 months ago

I had the same error when trying nextjs dynamic import too. PDF is huge

Penfu commented 1 week ago

@dev0T and for those using Zustand, you can access your store state (static) outside of React components using the getState() method.

This approach allows you to retrieve the current state without relying on hooks:

const someState = useStore.getState().someState;

Or destructure:

const { firstState, secondState } = useStore.getState();