【HTMLメール】React Email をReact -> HTML のレンダラーとして使ってみた

## これは何

React Email なるものが便利らしいと聞いたけど、具体的にどう使うのかやどう言う点が便利かがまとまっている記事がなさそうだったので書きました。

公式のデモはこちらで見ることができます。🔽

https://demo.react.email/preview/airbnb-review

## React Email とは

その名の通り、ReactでHTMLメールが作れるライブラリです。
用意されいているコンポーネントを組み合わせてHTMLメールを作っていくことができます。

### 何が嬉しい？

HTMLメールの実装は、基本Tableで組まないといけない&インラインで書かないといけないため、頭もコードも複雑になりがちです。

そこでReact Emailを使うと、コンポーネントを組み合わせることでよしなにレイアウトしてくれるので、作業時間の短縮と心の安寧を得ることができます。

React Emailを使って書いたコードと書き出されるhtmlを見比べてみると、その差が一目瞭然です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/3775b4c9-2b0f-bc35-f3de-265c1d5276b7.png)|
-|
左がReactで右が書き出されたHTML|

:::note warn
React Emailを使ってメールの送信までできるようなんですが、今回はレンダーとしての使用を想定しているので送信周りのことは説明していません。
:::

## React Emailを使えるようにする

では早速React Emailを使えるようにします。

自動セットアップとマニュアルセットアップの2種類があります。
公式サイトに手順があるのでこの通りに進めるとセットアップできます。
（私はマニュアルセットアップの方でセットアップしました）

https://react.email/docs/getting-started/automatic-setup

https://react.email/docs/getting-started/manual-setup

セットアップが完了すると`http://localhost:3000`で「Welcome to the React Email preview!」と書かれた画面が表示されます。


![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/0d23cf83-1160-102c-38b2-56575424f184.png)

サイドバーでファイルを選択すると、プレビューとソースが確認できます。

プレビュー|ソース
-|-
![プレビューが表示されます](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/fc3a345b-61c7-be58-910c-99ff712c0951.png)|![ソースが確認できます](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/afb940b0-2feb-8d21-7b82-2f3e77474258.png)

さらにソースで「HTML」を選択すると、HTMLでコードをコピーできるのでReactで書いてHTMLで書き出されたコードを使用することができます。便利！

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/d38bf130-630c-30c1-33bd-921d815aeacd.png)

## React Email でHTMLメールを作る

では実際どんなデザインが作れるのか、どれくらいスタイルを書く必要があるのかなどを見ていきます。

### レイアウト

基本は`<Container />`、`<Section />`、`<Row />`、`<Column />`を組み合わせてレイアウトを作っていくようです。

- `Container`
    - コンテンツを中央に配置してくれます
- `Section`
    - `Column`や`Rows`を使ってレイアウトを作ります
- `Column`
    - 縦に区切るレイアウトを作ります
- `Rows`
    - 行を作ります

🔽 例えばこんなレイアウトを組みたい場合

![2列に並んだアイテム、3列に並んだアイテム、ボタンが縦に並んでいるレイアウト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/2ef2e304-8e5c-9dbf-354b-f5cc6ddfc9b0.png)

🔽 コードはこんな感じになります

```typescript::index.tsx
export default function Email() {
  return (
    <Html>
      <Container style={container}>
        <Section style={section}>
          <Row>
            <Column>
              <Text>hogehoge</Text>
            </Column>
            <Column>
              <Text>hogehoge</Text>
            </Column>
          </Row>
          <Row>
            <Column>
              <Text>hogehoge</Text>
            </Column>
            <Column>
              <Text>hogehoge</Text>
            </Column>
            <Column>
              <Text>hogehoge</Text>
            </Column>
          </Row>
        </Section>
        <Section style={buttonWrapper}>
          <Column align="center">
            <Button style={button}>
              Click me
            </Button>
          </Column>
        </Section>
      </Container>
    </Html>
  );
}

const container = {
  padding: '12px',
  background: '#FFFFFF',
};

const section = {
  background: '##DFE0E0',
  textAlign: 'center',
};

const buttonWrapper = {
  paddingTop: 24,
};

const button = {
  padding: '4px 16px',
  background: '#FFFFFF',
  border: '2px solid #DFE0E0',
  borderRadius: 8,
};
```

## 使えるパーツ

デフォルトで用意されているパーツはこんな感じです。

- Heading （`h1`）
- Text （`p`）
- Hr （`hr`）
- Img （`img`）
- Link （`a`）
- Button （`a`）

とりあえず何もスタイル当てずに突っ込んだ状態がこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/b3639846-6973-bd66-554b-6a92aa8e0995.png)

```typescript:index.tsx
      <Container style={{background: '#ffffff', padding: 12}}>
        <Row style={row}>
          <Heading>Heading</Heading>
        </Row>
        <Hr />
        <Row style={row}>
          <Text>Text</Text>
        </Row>
        <Row style={row}>
          <Link href="">Link</Link>
        </Row>
        <Row style={row}>
          <Img src='blue.png' />
        </Row>
        <Row style={row}>
          <Button>Button</Button>
        </Row>
      </Container>
```

基本見た目を調整するスタイルは当たっていないので、セルフで書いていくことになります。
（個人的にはその方が作りやすくて嬉しい）


## React Emailを使ってHTMLメールを作るときのポイント

基本はHTMLメールを作る時と同じです。

### デザインする時の注意点

- position: absolute; や ネガティブマージンが使えないので、特殊な位置にはしない
- :hover や ::before などの疑似クラス・疑似要素が使えないのでそれが必要なデザインにしない

### コーディングする時の注意点

- テーブルレイアウトで作成する
    - これは React Emaiで用意されているコンポーネントを使えばいい感じにしれくれるので、そんな気にしなくて大丈夫です
- 使用できないCSSがある
    - 対応してないクライアントがある場合でも表示崩れしないかなどチェックする必要があります。
    - 例えば`background-image`や`border-radius`、`z-index`、`display:flex`や`grid`などが一部のメールクライアントでは使用できません。（2023年2月現在）
    - `margin`も部分的なサポートとなっており、適切に表示されない可能性があるので`padding`を使う必要があります。（このせいで不要なDOMが増える...）
    - https://www.campaignmonitor.com/css/ や https://www.caniemail.com/ でプロパティのサポート状況を調べることができます
- alt属性をきちんと書く
    - alt属性を適切に書くべきなのはHMTLメールに限った話ではないですが、画像がブロックされることがあるので画像が表示されない場合のためにalt属性を書いておく必要があります。