Library / SDK
MatthewHerbst/react-to-print avatar
MatthewHerbst/react-to-print

react-to-print: Printing React Components Through a Hidden Iframe

Print React components in the browser

2,475 stars236 forksTypeScriptMIT

At a glance

What is it?
react-to-print copies a referenced React subtree into an iframe and calls window.print on it. The mechanism is small, the print CSS rules are unforgiving, and mobile WebViews are a known dead end.
Who is it for?
Adopt react-to-print when you need a print button on a React page in a desktop browser and you are willing to write print CSS that targets the printed nodes directly. Do not adopt it if your users print from inside a WebView (Facebook, Slack in-app browsers), from Firefox on Android, or if your content lives behind react-redux's connect without an intermediate wrapper component.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 28 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap react-to-print fills between a React tree and window.print

Calling window.print() in a React app prints the whole document. The app shell, the navigation, the sidebar, the modal overlay and the button the user just clicked all land on the paper. The usual workaround is a @media print stylesheet that hides everything except one subtree, which works until the layout depends on flex or grid parents that are themselves hidden, at which point the printed output collapses. The README states the library's purpose plainly: "Print the content of a React component."

The audience is narrower than the download numbers suggest. This is for teams with a rendered React tree they already trust, where the print output should look like that tree rather than like a generated document. If you need paginated reports with repeating table headers, page numbers and a controlled page box, a document generator is a better fit. react-to-print gives you the browser's own print pipeline pointed at a subtree. It does not give you a layout engine.

How the iframe copy works, and why parent selectors stop applying

The hook returns a callback. When invoked, react-to-print creates a print iframe, clones the DOM nodes under contentRef into it, carries over the stylesheet and style tags, injects fonts listed in the fonts option, and calls print on the iframe's window. The iframe is removed afterwards unless preserveAfterPrint is set, which the README describes as useful for debugging by inspecting the print iframe. The print option replaces window.print entirely, which the README gives as the route for non-browser environments such as Electron.

The consequence of the copy is the single most common source of broken output, and the README calls it out under Common Pitfalls. Because only the printed subtree exists in the print DOM, its ancestors do not. A rule like div.parent p { color: red; } matches nothing if the printed root is the <p>. The README's instruction is direct: target all printed content directly and not from unprinted parents. This is not a bug to be worked around with specificity tricks. It is the design. Any stylesheet written against a full page hierarchy has to be audited before it will print correctly.

Styling defaults are handled by pageStyle, which the README says react-to-print sets to remove the header and footer most browsers add, and which you override to supply your own. ignoreGlobalStyles drops every style and link[type=stylesheet] tag, which is the escape hatch when global CSS is actively harmful to the printed page.

Installing react-to-print and printing a component

Install from npm. The package ships ESM and CommonJS builds with types, and the peer dependency range covers React 16.8 through 19, so the hook requires a React version that has hooks.

bash
npm install --save react-to-print

The README's usage example is the whole integration. A ref points at the content, the hook takes that ref, and the returned function is used as a click handler.

tsx
import { useReactToPrint } from "react-to-print";
import { useRef } from "react";

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

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

Clicking the button should open the browser's print dialog with only the contents of the referenced div. If nothing appears, the README's Known Issues section lists a TypeScript error, Type 'undefined' is not assignable to type 'ReactInstance | null', whose fix is to initialise the ref as useRef(null) rather than passing undefined.

The README documents a lazy variant for dynamic content, pointing at the LazyContent example, where the ref is set later rather than at mount. That example also covers setting the ref from non-React code such as a utility function, which matters when the print trigger lives outside the component tree. The repository's examples directory carries runnable versions of each scenario: BasicComponent, ComponentToPrint, CopyShadowRootContent, CustomPrint, DynamicDocumentTitle, LazyContent and OnBeforePrint. Cloning the repository and running the dev server via the start script is the fastest way to see the print iframe behaviour before wiring it into an application.

Page breaks, headers and footers, and the limits of pageStyle

The library does not paginate. Page breaks come from CSS applied to the copied nodes, which means break-inside, break-before and break-after rules on your own elements, and the browser decides where the cuts land. If a table row or a card straddles a boundary, that is a CSS problem in your stylesheet, not something the hook can correct. The README documents no pagination API, no page count, and no way to inject a running header or footer. pageStyle exists to override the base styles react-to-print injects, notably the ones removing browser-added headers and footers, so it is the place to set margins and page size, not a place to build repeating content.

The documentTitle option sets the title used when saving as a file, and accepts a function so a timestamp can be included. Two constraints apply. It is ignored when a custom print option is passed, and the README states under Common Pitfalls that it does not work when react-to-print runs inside an iframe. The suggested workaround is to set and restore the parent document's title manually using onBeforePrint and onAfterPrint, which only works if your script can reach the parent document.

onBeforePrint returns a Promise, and the README presents it as the way to change page content before printing, as an alternative to or alongside @media print queries. A rejection there is one of the two cases that routes into onPrintError, the other being a rejection from print. That error surface is narrow by the README's own description: serious failures only, currently limited to those two promise rejections.

Where react-to-print fails: WebViews, Firefox Android, and Safari timing

Mobile WebViews are the clearest failure. The README states that printing within a WebView, when the page is opened by an app such as Facebook or Slack rather than the full browser, is known to generally not work, because some WebViews do not expose the correct API and others expose it but cause printing to no-op. The README says the project is researching resolutions and that a fix likely requires changes by Google/Chromium and Apple/WebKit, referencing issue 384. That is an external dependency, not a backlog item, so treat in-app browser printing as unsupported.

Firefox on Android is listed as a known incompatible browser because it does not support window.print. Separately, the README notes that some mobile browsers open the native Share action instead of printing. On newer Safari versions, onAfterPrint may fire immediately, before the print dialog closes, because window.print does not block. Any state you reset in onAfterPrint, such as a loading flag or a modal, can therefore reset too early on that browser.

There is a React-specific trap as well. The connect method from react-redux returns a functional component that cannot be assigned a reference for contentRef. The README's fix is an intermediate component that simply renders your connected component. If your printable content sits behind connect and you have not added that wrapper, the ref will not resolve and there will be nothing to print.

react-to-print compared with react-pdf and print stylesheets

The closest alternative is react-pdf, which takes the opposite approach. react-to-print hands your existing DOM to the browser's print pipeline, so what you print is what you rendered, and the browser owns pagination. react-pdf builds a document model with its own component primitives and renders a PDF, so you get explicit control over pages, and you give up the ability to print your existing components unchanged. The choice is usually decided by the output: a receipt or a label that should match the screen goes to react-to-print; a multi-page report with fixed page geometry goes to a document renderer.

The other alternative is doing nothing, and using a @media print stylesheet that hides everything except one container. That avoids a dependency and keeps the real DOM in place, which sidesteps the parent-selector problem entirely, since ancestors still exist. It breaks down when the printable region is a modal or a portal, when the surrounding layout constrains the printed subtree, or when you need to print something that is not currently mounted. react-to-print handles those cases by copying the nodes into a clean document. The trade is that you inherit the copy's restrictions.

Maintenance, licence and what upgrading costs

The last push to the repository was on 2026-09-14, and the repository is not archived. The most recent release listed is v3.3.0 from 2026-02-23, following v3.2.0 in October 2025 and v3.1.1 in July 2025. The package is published under the MIT licence, and the repository contains a LICENSE file at the top level. MIT permits commercial use and modification; it also means the maintainers carry no warranty, and the WebView limitation described in the README is not something a licence change would alter. This is a description of the licence terms, not legal advice.

The dependency surface is small. React is a peer dependency spanning 16.8 through 19, so the library does not pin your React version. The published package contains only the dist directory, with ESM and CommonJS entry points and bundled types. Upgrade cost concentrates in two places: the option table, which is the API surface, and any print CSS written against the copy behaviour. A major version bump is where the option names would move, so reading CHANGELOG.md before upgrading is the practical step. There is no runtime service and no server component, so there is nothing to operate.

Editorial conclusion

Adopt react-to-print when you need a print button on a React page in a desktop browser and you are willing to write print CSS that targets the printed nodes directly. Do not adopt it if your users print from inside a WebView (Facebook, Slack in-app browsers), from Firefox on Android, or if your content lives behind react-redux's connect without an intermediate wrapper component. Before committing, verify three things: that your stylesheet has no descendant selectors spanning unprinted parents, that onAfterPrint firing early on new Safari builds does not break your UI state, and that you have read the print CSS section of the README against your own stylesheet.

Frequently asked questions

How do I use react-to-print in a React component?

Create a ref with useRef, pass it to useReactToPrint as contentRef, and attach the same ref to the element you want printed. The hook returns a function you use as the click handler. The README's example uses useRef<HTMLDivElement>(null) and a button whose onClick is that returned function.

What is react-to-print in React JS?

It is an npm package that prints the content of a React component. It copies the referenced subtree into a print iframe and calls the browser's print function on it, and it exposes options such as contentRef, pageStyle, documentTitle and onBeforePrint.

How does react-to-print compare with react-pdf?

react-to-print prints your existing rendered DOM through the browser's print pipeline, so pagination is the browser's job. react-pdf is a document renderer with its own component model and explicit page control. Choosing between them usually comes down to whether the printout must match the on-screen component or must follow a fixed page layout.

Can I print a PDF with react-to-print?

The library prints the content of a React component through the browser's print dialog, where the user can choose a PDF destination. It does not generate a PDF file itself. If you need a generated PDF document, react-to-print is the wrong tool.

Official sources

  1. License: MIT
  2. MatthewHerbst/react-to-print on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/matthewherbst-react-to-print.svg)](https://hysenlabs.com/projects/matthewherbst-react-to-print)