• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

gregnb/react-to-print: Print React components in the browser. Supports Chrome, S ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

gregnb/react-to-print

开源软件地址:

https://github.com/gregnb/react-to-print

开源编程语言:

TypeScript 84.8%

开源软件介绍:

react-to-print logo

ReactToPrint - Print React components in the browser

NPM Downloads npm version

So you've created a React component and would love to give end users the ability to print out the contents of that component. This package aims to solve that by popping up a print window with CSS styles copied over as well.

Demo

Run react-to-print

Install

npm install --save react-to-print

API

<ReactToPrint />

The component accepts the following props:

Name Type Description
bodyClass? string One or more class names to pass to the print window, separated by spaces
content function A function that returns a component reference value. The content of this reference value is then used for print
copyStyles? boolean Copy all <style> and <link type="stylesheet" /> tags from <head> inside the parent window into the print window. (default: true)
documentTitle? string Set the title for printing when saving as a file
fonts? { family: string, source: string }[] You may optionally provide a list of fonts which will be loaded into the printing iframe. This is useful if you are using custom fonts
onAfterPrint? function Callback function that triggers after the print dialog is closed regardless of if the user selected to print or cancel
onBeforeGetContent? function Callback function that triggers before the library gathers the page's content. Either returns void or a Promise. This can be used to change the content on the page before printing
onBeforePrint? function Callback function that triggers before print. Either returns void or a Promise. Note: this function is run immediately prior to printing, but after the page's content has been gathered. To modify content before printing, use onBeforeGetContent instead
onPrintError? function Callback function (signature: `function(errorLocation: 'onBeforePrint'
pageStyle? string or function We set some basic styles to help improve page printing. Use this to override them and provide your own. If given as a function it must return a string
print? function If passed, this function will be used instead of window.print to print the content. This function is passed the HTMLIFrameElement which is the iframe used internally to gather content for printing. When finished, this function must return a Promise. Use this to print in non-browser environments such as Electron
removeAfterPrint? boolean Remove the print iframe after action. Defaults to false
suppressErrors? boolean When passed, prevents console logging of errors
trigger? function A function that returns a React Component or Element. Note: under the hood, we inject a custom onClick prop into the returned Component/Element. As such, do not provide an onClick prop to the root node returned by trigger, as it will be overwritten
nonce? string Set the nonce attribute for whitelisting script and style -elements for CSP (content security policy)

PrintContextConsumer

If you need extra control over printing and don't want to specify trigger directly, PrintContextConsumer allows you to gain direct access to the handlePrint method which triggers the print action. Requires React >=16.3.0. See the examples below for usage.

useReactToPrint

For functional components, use the useReactToPrint hook, which accepts an object with the same configuration props as <ReactToPrint /> and returns a handlePrint function which when called will trigger the print action. Requires React >=16.8.0. See the examples below for usage.

Compatibility

react-to-print should be compatible with most major browsers. We also do our best to support IE11.

Mobile Browsers in WebView

While printing on mobile browsers should work, printing within a WebView (when your page is opened by another app such as Facebook or Slack, but not by the full browser itself) is known to not work on many if not all WebViews. Some don't make the correct API available. Others make it available but cause printing to no-op when in WebView.

We are actively researching resolutions to this issue, but it likely requires changes by Google/Chromium and Apple/WebKit. See #384 for more information. If you know of a way we can solve this, your help would be greatly appreciated.

Known Incompatible Browsers

Examples

Run react-to-print

// Using a class component, everything works without issue
export class ComponentToPrint extends React.PureComponent {
  render() {
    return (
      <div>My cool content here!</div>
    );
  }
}

// Using a functional component, you must wrap it in React.forwardRef, and then forward the ref to
// the node you want to be the root of the print (usually the outer most node in the ComponentToPrint)
// https://reactjs.org/docs/refs-and-the-dom.html#refs-and-function-components
export const ComponentToPrint = React.forwardRef((props, ref) => {
  return (
    <div ref={ref}>My cool content here!</div>
  );
});

Calling from class components

import React from 'react';
import ReactToPrint from 'react-to-print';

import { ComponentToPrint } from './ComponentToPrint';

class Example extends React.PureComponent {
  render() {
    return (
      <div>
        <ReactToPrint
          trigger={() => {
            // NOTE: could just as easily return <SomeComponent />. Do NOT pass an `onClick` prop
            // to the root node of the returned component as it will be overwritten.
            return <a href="#">Print this out!</a>;
          }}
          content={() => this.componentRef}
        />
        <ComponentToPrint ref={el => (this.componentRef = el)} />
      </div>
    );
  }
}

Calling from class components with PrintContextConsumer

import React from 'react';
import ReactToPrint, { PrintContextConsumer } from 'react-to-print';

import { ComponentToPrint } from './ComponentToPrint';

class Example extends React.PureComponent {
  render() {
    return (
      <div>
        <ReactToPrint content={() => this.componentRef}>
          <PrintContextConsumer>
            {({ handlePrint }) => (
              <button onClick={handlePrint}>Print this out!</button>
            )}
          </PrintContextConsumer>
        </ReactToPrint>
        <ComponentToPrint ref={el => (this.componentRef = el)} />
      </div>
    );
  }
}

Calling from functional components

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

import { ComponentToPrint } from './ComponentToPrint';

const Example = () => {
  const componentRef = useRef();

  return (
    <div>
      <ReactToPrint
        trigger={() => <button>Print this out!</button>}
        content={() => componentRef.current}
      />
      <ComponentToPrint ref={componentRef} />
    </div>
  );
};

Calling from functional components with useReactToPrint

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

import { ComponentToPrint } from './ComponentToPrint';

const Example = () => {
  const componentRef = useRef();
  const handlePrint = useReactToPrint({
    content: () => componentRef.current,
  });

  return (
    <div>
      <ComponentToPrint ref={componentRef} />
      <button onClick={handlePrint}>Print this out!</button>
    </div>
  );
};

Note (401): In TypeScript, if you encounter componentRef.current error such as: Type 'undefined' is not assignable to type 'ReactInstance | null'., add null inside the useRef():

const componentRef = useRef(null);

Known Issues

  • onAfterPrint may fire immediately (before the print dialog is closed) on newer versions of Safari where window.print does not block

Common Pitfalls

  • documentTitle will not work if react-to-print is running within an iframe. If react-to-print is running within an iframe and your script has access to the parent document, you may be able to manually set and then restore the parent document's title during the print. This can be done by leveraging the onBeforeGetContent and onAfterPrint props.

  • When printing, only styles that directly target the printed nodes will be applied, since the parent nodes will not exist in the DOM used for the print. For example, in the code below, if the <p> tag is the root of the ComponentToPrint then the red styling will not be applied. Be sure to target all printed content directly and not from unprinted parents.

    <div className="parent">
      <p>Hello</p>
    </div>
    div.parent p { color:red; }
  • The connect method from react-redux returns a functional component that cannot be assigned a reference to be used within the content props' callback in react-to-print. To use a component wrapped in connect within content create an intermediate class component that simply renders your component wrapped in connect. See 280 for more.

  • Using a custom component as the return for the trigger props is possible, just ensure you pass along the onClick prop. See 248 for an example.

  • When rendering multiple components to print, for example, if you have a list of charts and want each chart to have its own print icon, ideally you will wrap each component to print + print button in its own component, and just render a list of those components. However, if you cannot do that for some reason, in your .map ensure that each component gets a unique ref value passed to it, otherwise printing any of the components will always print the last component. See 323 for more.

FAQ

Can react-to-print print a PDF?

We simply open the browser's print preview window, so we aren't able to print a PDF as we lose control once the print preview window opens. However, it should be very easy to use react-to-print to take the information you need an pass it to a library that can generate a PDF.

const handlePrint = useReactToPrint({
  ...,
  print: async (printIframe: HTMLIframeElement) => {
    // Do whatever you want here, including asynchronous work
    await generateAndSavePDF(printIframe);
  },
});

For examples of how others have done this, see #484

Can the ComponentToPrint be a functional component?

Yes, but only if you wrap it with React.forwardRef. react-to-print relies on refs to grab the underlying DOM representation of the component, and functional components cannot take refs by default.

Why does onAfterPrint fire even if the user cancels printing

onAfterPrint fires when the print dialog closes, regardless of why it closes. This is the behavior of the onafterprint browser event.

Why does react-to-print skip <link rel="stylesheet" href=""> tags

<link>s with empty href attributes are invalid HTML. In addition, they can cause all sorts of undesirable behavior. For example, many browsers - including modern ones, when presented with <link href=""> will attempt to load the current page. Some even attempt to load the current page's parent directory.

Note: related to the above, img tags with empty src attributes are also invalid, and we may not attempt to load them.

How do you make ComponentToPrint show only while printing

If you've created a component that is intended only for printing and should not render in the parent component, wrap that component in a div with style set to { display: "none" }, like so:

<div style={{ display: "none" }}><ComponentToPrint ref={componentRef} /></div>

This will hide ComponentToPrint but keep it in the DOM so that it can be copied for printing.

Changing print settings in the print dialog

Unfortunately there is no standard browser API for interacting with the print dialog. All react-to-print is able to do is open the dialog and give it the desired content to print. We cannot modify settings such as the default paper size, if the user has background graphics selected or not, etc.

Printing video elements

react-to-print tries to wait for video elements to load before printing but a large part of this is up to the browser. Further, the image displayed will usually be the first frame of the video, which might not be what you expect to show. To ensure the proper image is displayed in the print we highly recommend setting the poster attribute of the video, which allows specifying an image to be a placeholder for the video until the video loads.

Electron

react-to-print can be used for printing in Electron, but you will need to provide your own print method since Electron does not natively support the window.print method. Please see this answer on StackOverflow for how to do this.

There is a fully-working example of how to use react-to-print with Electron available here.

Helpful Style Tips

Set the page orientation

While you should be able to place these styles anywhere, sometimes the browser doesn't always pick them up. To force orientation of the page you can include the following in the component being printed:

<style type="text/css" media="print">{"\
  @page {\ size: landscape;\ }\
"}</style>

Set custom margin to the page (29)

To set custom margin to the page,

First, create a function to return the page margin,

const getPageMargins = () => {
  return `@page { margin: ${marginTop} ${marginRight} ${marginBottom} ${marginLeft} !important; }`;
};

Now, within the JSX call this function within the style tags,

<style>{getPageMargins()}</style>

PS: This style tag should be inside the component that is being passed in as the content ref.

Set landscape printing (240)

In the component that is passed in as the content ref, add the following:

@media print {
  @page { size: landscape; }
}

Printing elements that are not displayed (159)

Instead of using { display: 'none'; }, try using { overflow: hidden; height: 0; }

Using the pageStyle prop

The pageStyle prop can be used to set anything from simple to complex styles. For example:

const pageStyle = `
  @page {
    size: 80mm 50mm;
  }
 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap