ReactでWebアプリを作成する際、表示内容を印刷する機能を作ることがあります。
react-to-printというライブラリを使うことで、割と楽にDOMを印刷することができたので、備忘録としてやり方などを記載します。
react-to-printのインストール
npmなどでインストールできます。僕はyarnを使うので、
$ yarn add react-to-print
でプロジェクトファイルにいれます。
使い方
import { FC, useRef } from 'react'
import ReactToPrint from 'react-to-print'
const PrintComponent: FC = () => {
const componentRef = useRef<HTMLDivElement>(null)
return (
<>
<div ref={componentRef}>印刷したいDOM</div>
<ReactToPrint
trigger={() => (
<button>
<div>ボタン要素的なもの</div>
</button>
)}
pageStyle="@page { size: A4 landscape; margin: 0; }"
content={() => componentRef.current}
/>
</>
)
}
上記のような感じで使えます。
yarn startなどで立ち上げたアプリ上でbuttonタグのボタンを押下すると、印刷用プレビューページ(ブラウザ機能のやつ)が開き印刷内容が確認できるはずです。
ポイントは、useRefを使って印刷対象のDOM要素を参照し、その参照をReactToPrintコンポーネントのcontentに渡しているところです。
参照する要素をうまく変えれば、表示しているページの中の一部だけ印刷する、ということも可能です。
Tips
pageStyleでできること
pageStyleというパラメータで、印刷設定用のCSSを渡すこともできます。
横長の要素を印刷したい場合はsize: A4 landscape;という形でlandscapeをつければ横向き印刷のプレビューを表示してくれます。
また、size: A4;に納めるための縦横それぞれのpx値は、僕が測ってみた限り792x1144でした。(ブラウザ環境その他でもしかすると変わってくるかもしれませんが)
上記より大きいDOMを印刷しようとすると印刷プレビューからはみ出てしまいますが、size: A3;などと指定すれば上記の許容px数が増えて印刷プレビューからはみ出なくなります。
A3と指定しても、印刷時に印刷機の方でA4紙を指定すれば普通にA4で印刷できるため、大きすぎるDOMを印刷したい場合は検討してみてください。
margin: 0;はChromeだけ
pageStyleの中でmargin: 0;と指定していますが、こちらはページ名やページ数などのメタ情報を印刷させなくする工夫です。ただGoogleChromeしか適用されないそうなので使用時にはご注意をお願いします。
ページを分けて印刷したい時
react-to-printとは直接関係ない話になりますが、1ページ目から2ページ目などとページを跨ぎたい場合は、<section></section>で囲みつつ、page-break-after: always;のstyleを当てることで各ページのセクションを分けることができます。
import { FC, useRef } from 'react'
import ReactToPrint from 'react-to-print'
const PrintComponent: FC = () => {
const componentRef = useRef<HTMLDivElement>(null)
return (
<>
<div ref={componentRef}>
<section style={{page-break-after: always;}}>1ページ目</section>
<section style={{page-break-after: always;}}>2ページ目</section>
</div>
<ReactToPrint
trigger={() => (
<button>
<div>ボタン要素的なもの</div>
</button>
)}
pageStyle="@page { size: A4 landscape; margin: 0; }"
content={() => componentRef.current}
/>
</>
)
}
最後に
react-to-printはReactアプリでDOMを印刷したくなった際に、かなり手軽に実現できるライブラリです。印刷で困っている方の助けになれば幸いです。