react-to-printで詰まったところmemo

何者?

「Web画面をPDFで印刷したい、PDFで出力したい」をReactで実現してくれるライブラリ

https://www.npmjs.com/package/react-to-print

  • 基本的に↑の例を見れば、サクッとできる。
  • しかもDemoもあるので、参考になる

・・・・が、今回、関数コンポーネントでTypeScriptで書いている場合にサンプルコードだけでは、詰まった部分があったので、メモ

業務で書いたコードを加工してるので、あくまでイメージです。(動作確認してません

同じような境遇になった人の何かのヒントになれば良いなと思います。(あと、将来の自分用に残しておく、多分半年後何も覚えてない。)

(TypeScriptを含め、frontendは全体的に勉強中なので間違えているところもあるかもですが・・・優しい目で見てあげてください 🙇‍♀️ )

ComponentToPrint の部分

import React, { Component, useRef } from "react";

class ComponentToPrint extends Component {
  public render(): JSX.Element {
    return (
      <>
         <SampleComponent1 /> <- こんな感じで、複数のコンポーネントは並べられる
         <SampleComponent2 />
      </>
    );
  }
}

ReactToPrint の部分

  • ReactToPrint と ComponentToPrintの順番はどっちでも動きそうです
  • ボタンを上に置くか、下に置くか見たいなところ
import React, { useRef } from 'react';
import ReactToPrint from 'react-to-print';
import Button from "@material-ui/core/Button";

import { ComponentToPrint } from './ComponentToPrint';

export const Exsample = () => {
  const componentRef = useRef(null);
  return (
    <div>  <- useRefに認識させるために div で囲う必要がある(と理解)
      <ComponentToPrint ref={componentRef} />  <- ref ってやつがクラスコンポーネントじゃないと使えないみたい
      <ReactToPrint
        trigger={() => (
          <Box textAlign="right"> <- material-uiも使えますよ!
            <Button>
              印刷
            </Button>
          </Box>
        )}
        content={() => componentRef.current}
        documentTitle={ここに保存時のファイル名をデフォルトを設定できる}
      />
    </div>
  );
};

使ってみて分かったこと

ComponentToPrint の部分はクラスコンポーネントにする
  • 現状、クラスコンポーネントじゃないとうまく動作しないようです
  • 次のメジャーアップデートで、関数コンポーネントにも対応させるとのコメントも見かけましたので、とりあえずクラスコンポーネントにしましょう
  • FAQにも書いてありますね、抜粋
Can the ComponentToPrint be a functional component?
Officially no, but there are workarounds using the useRef hook.
See #96 and #181 for examples. 
We will officially support this once we release the next major version which will drop React 15 support.

ここら辺のissueにも書いてあるので、ざっと読んでみると良いかと思います。

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

頑張れば関数コンポーネントも使えるみたいなコメントもあります↓

https://github.com/gregnb/react-to-print/issues/181#issuecomment-814305408

こちらはHOC(higher-order component; HOC)というReactの応用テクニックらしいですね。

あるコンポーネントを受け取り、新規コンポーネントを返す関数 のことらしいです

https://ja.reactjs.org/docs/higher-order-components.htm

結局分からなかったこと

pageStyle について
  • ReactToPrint に渡すと、PDFのページのmarginとかの設定を一括でできるらしいと使ったが、material-uiのデザインが吹っ飛ぶ(反映されなくなる)ので、結局使えなかった
  • PDFの周囲に空白入れたかったが断念
改行ページ
  • サンプルコードの通りに書いたがうまくいかない(使い方間違えている疑惑)
  • https://www.npmjs.com/package/react-to-print のPage Breaks のところにサンプルコードもあるので、もう一回ちゃんと読めばできそうな気がする(気のせいかも)