MatthewHerbst / react-to-print

Print React components in the browser. Supports Chrome, Safari, Firefox and EDGE
MIT License
2.15k stars 220 forks source link

useReactToPrint is not working / dose not exist at 3.0.2 version #762

Closed urlsab closed 2 weeks ago

urlsab commented 2 weeks ago

this basic code example, that i took from the docs

const contentRef = useRef<HTMLDivElement>(null);
const reactToPrintFn = useReactToPrint({ contentRef });

return (
  <div>
    <button onClick={reactToPrintFn}>Print</button>
    <div ref={contentRef}>Content to print</div>
  </div>
);

have this error:

Uncaught ReferenceError: useRef is not defined
    at App.jsx:5:20

so i add use ref, and i got this:

App.jsx:6 Uncaught ReferenceError: useReactToPrint is not defined
    at App.jsx:6:24

so i import useReactToPrint (??? how exactly ?)

and i got this error :

Uncaught TypeError: useReactToPrint is not a function
    at App.jsx:5:24

this is my final code after all errors:

import React, { useRef } from 'react';
import useReactToPrint from'react-to-print';

const contentRef = useRef<HTMLDivElement>(null);
const reactToPrintFn = useReactToPrint({ contentRef });

const App = () => {
  return (
    <div>
      <button onClick={reactToPrintFn}>Print</button>
      <div ref={contentRef}>Content to print</div>
    </div>
  )
}

export default App;
MatthewHerbst commented 2 weeks ago

Hello. Apologies, the docs definitely assume some familiarity, I'll look to improve them in the future. The export is named, not default. So it should be:

import { useReactToPrint } from 'react-to-print';
urlsab commented 2 weeks ago

I add your fix :

import React, { useRef } from 'react';
import { useReactToPrint } from'react-to-print';

const App = () => {

  const contentRef = useRef<HTMLDivElement>(null);
  const reactToPrintFn = useReactToPrint({ contentRef });

  return (
    <div>
      <button onClick={reactToPrintFn}>Print</button>
      <div ref={contentRef}>Content to print</div>
    </div>
  )
}

export default App;

but I got this:

Unexpected Application Error!
Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref
Error: Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref
    at coerceRef (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:9896:25)
    at createChild (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:10090:34)
    at reconcileChildrenArray (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:10282:33)
    at reconcileChildFibers2 (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:10559:24)
    at reconcileChildren (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:14290:37)
    at updateHostComponent (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:14807:11)
    at beginWork (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:15935:22)
    at beginWork$1 (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:19753:22)
    at performUnitOfWork (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:19198:20)
    at workLoopSync (http://localhost:5175/node_modules/.vite/deps/chunk-M7F2YF5A.js?v=0cc005c9:19137:13)
💿 Hey developer 👋

You can provide a way better UX than this when your app throws errors by providing your own ErrorBoundary or errorElement prop on your route.
urlsab commented 2 weeks ago

Now I removed <HTMLDivElement> from const contentRef = useRef<HTMLDivElement>(null); and it's working.

you can copy this code to your docs:

import React, { useRef } from 'react';
import { useReactToPrint } from'react-to-print';

const App = () => {

  const contentRef = useRef(null);
  const reactToPrintFn = useReactToPrint({ contentRef });

  return (
    <div>
      <button onClick={reactToPrintFn}>Print</button>
      <div ref={contentRef}>Content to print</div>
    </div>
  )
}

export default App;
MatthewHerbst commented 2 weeks ago

Hmm. The application error is runtime, but the types are build time. Removing the types should have zero impact on what happens at runtime.

urlsab commented 2 weeks ago

Look here, removing the types dose impact on what happens at runtime!

MatthewHerbst commented 2 weeks ago

Fascinating. That is very strange! I wonder if Vite is doing something different based on the type. We use Vite at my company as well but I don't manage it so am not super familiar with the details. Does changing the file extensions from .jsx -> .tsx do anything? (I don't think it should, but I'm just very confused!)

urlsab commented 2 weeks ago

You can see here, that changing the file extensions from .jsx -> .tsx cause error, with <HTMLDivElement>

tsxAtReactToPrint

or without

tsxReactPrintErrorWithoutTag
MatthewHerbst commented 2 weeks ago

You should be able to solve that type error by making this change:

// Before
<button onClick={reactToPrintFn}>Print</button>;

// After
<button onClick={() => reactToPrintFn()}>Print</button>;

The reason for this is that the returned function should not be nakedly passed to an onClick. It will work if you do that (since non-TypeScript users wouldn't be able to figure out the issue), but ideally you wrap it.

urlsab commented 2 weeks ago

OK thanks a lot

MatthewHerbst commented 2 weeks ago

Please let me know if you run into other issues! I'll look to improve the docs soon