ゆとり日記

心にゆとりを持って生きたいプログラマーの雑記です。気が向いたら書きます。

React Portalでmodalのレンダリング位置を制御する

Reactでmodalを実装する際に便利なものがあったのでブログに纏めてみます。ちなみに、React 16時代から利用できる機能なので目新しい話題ではないことを冒頭で断っておきます。

参考 : React v16の機能紹介

React Portalについて

React Portal は簡単に言うと「子コンポーネントレンダリングするDOMノードを指定する」仕組みです。Reactでは大元となるDOMに対してコンポーネントの親子関係を構築していくのが基本ですが、DOMの階層に外にいるDOMノードにコンポーネントレンダリングしたいケースも起こりえます。その際に利用するのがReact Portalです。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex">
  </head>
  <body>
    <!-- 大元となるDOM -->
    <div id="react-root"></div>
    <!-- React Portalを使用したレンダリング先となるDOM -->
    <div id="portal-root"></div>
  </body>
</html>

言葉では伝わりづらいので、実際のHTMLも載せてみます。主要なコンポーネントレンダリングされるのはid「react-root」のdivですが、特定のコンポーネントをid「portal-root」のdivに対してのレンダリングが可能になるのです。

modal実装時の悩みどころ

要素に「重なり順」という関係性が生まれ、子要素が親要素の下に表示されるのはHTMLの基本です。ですが、modalは親を飛び越えていく必要があります。

modalの表示に支障が出ているHTMLのサンプルを実際に作ってみました。

https://codepen.io/rukiadia/pen/gOxBvNz

modalがサイドメニューの下に潜り込んでしまう様子
modalがサイドメニューの下に潜り込んでしまう様子

私が作成したサンプルでは、modalが画面左のサイドメニューの下に潜り込んでいます。modal要素は画面全体に広がる挙動を想定されるので、この見た目は違和感を感じざるをえません。要素の重なり順をz-indexで複雑に制御しているアプリケーションでは、このような状況が容易に起こりえます。

【余談】 z-indexについて理解を深めたい方は「z-index」「スタッキングコンテキスト」をキーワードに参考記事を探してみるのがオススメです。

React Portalを使ってみる

import React from 'react'
import { createPortal } from 'react-dom'

const modalRoot = document.createElement('div')
modalRoot.setAttribute('id', 'portal-root')
document.body.appendChild(modalRoot)

export const Modal: React.FC<Props> = ({ children, closeModal, isOpen }) => {
  return createPortal(
    isOpen ? (
      <Overlay onClick={closeModal}>
        <Container onClick={(event) => event.stopPropagation()}>
          {children}
        </Container>
      </Overlay>
    ) : null,
    modalRoot
  )
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex">
  </head>
  <body>
    <!-- 大元となるDOM -->
    <div id="react-root"></div>
    <!-- レンダリング先のDOMをModalコンポーネントが動的に生成 -->
    <!-- <div id="portal-root"></div> -->
  </body>
</html>

「親コンポーネントから渡されるchildrenをmodal内に表示」「modalのレンダリング先となるDOMを生成」の2つの役割を持つコンポーネントのコード例です。(必要最低限のコードにするため、CSSの記述などは意図的に省いてます)

レンダリング先のDOMをあらかじめ用意することも可能ですが、modalに関する事情をコンポーネント内に纏めたかったのでこうしています。また、テストコードが書きやすくなる利点もあるので、動的に生成する手法がオススメです。

参考 : Testing LibraryのModalテストコード例

まとめ

以上がReact Portalの仕様例の説明になります。

react-modal のようなライブラリを使用すれば必要のない苦労にはなりますが、自作したいケースもあるかもしれません。その場合はReact Portalを使用することで「画面の表示」と「コンポーネント構造」を切り離して実装を進めていくと、開発が楽になる筈です。

9月の振り返り

9月が終わってから十日経っているので今更感がありますが、後でふり返れるようにブログを書いておきます。

9月にやったこと

9月の前半はAWS認定の試験準備、9月の後半はPHP Conferenceの準備に追われてる状態でした。

AWS認定の勉強

7月に合格したCloud Practitionerと違い、AWS公式のトレーニングの中にいい感じのものがなく、最終的にUdemyの講座に落ち着きました。英語音声・英語字幕でしたが、講師の方が話す英語に癖が少なく、聞き取りはそこまで難しくありません。

https://www.udemy.com/course/aws-certified-developer-associate-dva-c01/ www.udemy.com

出題範囲となるサービスの中で理解が浅いものを順次動かし、手になじませる練習をひたすらやっていました。試験ガイドが公開されているので、自信がない箇所を初めに洗い出しておくと勉強の効率がいいと思います。

PHP Conferenceへの参加

今回のPHP Conferenceも非常に楽しかったです。discordも昨年よりも盛り上がっていて、オフラインと同等とはいかないまでもカンファレンスらしい熱気を感じられるイベントだったと思います。

個人的にささったトークテーマは『PHPで学ぶオブジェクト指向プログラミング入門』、『SPAセキュリティ入門』の2つでした。懇親会で参加者の人ともっと話をしてみたかったんですが、登壇が終わって緊張の糸が切れたせいか、当日は早寝をしてしまったのが心残りでしたね。

登壇の話

今回のトークテーマはこちらでした。

fortee.jp

speakerdeck.com

最初はDockerイメージの軽量化に話題を寄せるつもりでしたが、最終的にPHPのオフィシャルイメージを読み解く内容に変更しました。PHPカンファレンスらしい話をしたかったというのが主な理由です。

実際にどうするかは分かりませんが、イメージ軽量化の話は来年のPHPerKaigiでCFP出してみてもいいかもしれないですね。

まとめ

登壇をぼちぼち継続できてますし、AWSへの苦手意識もかなり薄れました。2021年の夏はそこそこの成果を出せたんじゃないかと思います。

秋冬は英語の勉強をちゃんとやって、来年の春はコンピュータサイエンスの学士を取得する道を歩めるように頑張っていきます。

AWS Certified Cloud Practitionerに合格した

「一番簡単なAWS試験に受かったくらいでブログを書くの?」と言われるかもしれないですが、インフラに対して人一倍苦手意識を持ってる僕にとっては大きなステップなので、周りを気にせずにブログを書きます。

なんでAWS資格を取ることにしたのか?

AWSを雰囲気で使ってる」状態を脱して、インフラに対する抵抗感・恐怖感をなくしたかったからです。資格が全てとは思っていませんが、他者に対する知識の証明にもなりますし、自分への肯定感に繋がります。それに何より、資格を持っていて損をすることはない筈だと考えました。

試験準備に何をしたのか

  • AWS公式が提供しているトレーニング動画を見る。
  • AWSではじめるインフラ構築入門」を読んで、実際にインフラを構築する。

以上の2点です。体系的な知識を学んだ後、実際に手を動かして知識を実践する流れを取りました。

AWS公式のトレーニン

AWS 認定試験に備える

受験を考えるまでは知らなかったんですが、AWSは公式のトレーニング教材を数多く提供してくれています。「AWS Certified Cloud Practitioner」も例外ではなく、教材となる動画があります。音声は英語ですが、日本語字幕があるので英語に抵抗がある人でも問題なく見れると思います。

AWSではじめるインフラ構築入門」でインフラ構築

www.shoeisha.co.jp

アプリケーションエンジニアである以上、知識として知っているだけでは十分ではありませんし、実際に手を動かす方がが知識の定着を見込めます。元々は資格勉強のために買ったわけではありませんでしたが・・結果的に非常に役立ちました。

本の内容はTwitterライクなSNSアプリケーションをEC2インスタンスにデプロイして動かすというものです。

このような流れでリアルなアプリケーション構築をなぞることができます。普段の仕事でVPCの構築をおこなったことがなかったので、実際にやってみるのは非常に楽しい経験でした。試験の範囲に含まれていない部分もありますが、手を動かすことが知識の定着の大きな助けになりました。

今後どうするか

基礎は基礎で手応えがある内容でしたが、アプリケーション開発の知識はもう少し欲しいところです。プロフェッショナルまで取ることは現時点では考えていませんが、8月〜9月に認定アソシエイトの試験は受けてみようと考えています。

『オブジェクト指向UIデザイン』を読んだ感想

はじめに

www.amazon.co.jp

UIデザインを学ぶ必要性を感じたので、積ん読にしていた本を読んでみました。この本を読む前は『はじめてのUIデザイン』を読んでいて、次は実際に手を動かすステップがある本を求めていたら、『オブジェクト指向UIデザイン』にたどり着きました。

オブジェクト指向UI」とはどんなものだった?

この本では、エンジニアとしては馴染みのある概念である「オブジェクト」をデザインを考えるために使用しており、「オブジェクト = ユーザーの目当て」と表現しています。この場合の「目当て」とは、AmazonのようなECサイトであれば「商品」となり、はてなブログやnoteのようなコンテンツを扱うサービスであれば「コンテンツ」となります。目当てとなるオブジェクトを中心にユーザーが行う行動を設計していく手法がこの本では語られています。

  • ECサイトの「商品」に対する行動
    • 詳細を見る
    • 検索する
    • 「欲しい物リスト」や「気になるリスト」に入れる
    • バスケットに入れる

このように「オブジェクト = ユーザーの目当て」を中心に行動を考えていきます。つまり、UIデザインを実際に始める前に、アプリケーションのメインが何になるのかを先に考えていきます。

オブジェクト指向UI」とは逆の「タスク指向UI」

オブジェクトではなく、タスクを中心に考える手法です。ECサイトを例に言語化するとm「〜を買う」の動詞に対して、名詞である「商品」を引数として渡すイメージです。

この本では銀行のATMを例に挙げていました。最初の画面で利用者に行動(引き出し、振り込み等)を選択させるUIとなりますが、ATMの場合は「タスク指向UI」が機能する例として扱われています。何故なら、ATMで扱うオブジェクトは「口座」のみだからです。

現実でありがちな「タスク指向UI」

現実世界のやり取りをそのままUIに落とし込むと「タスク指向UI」になりやすいと個人的には考えています。ここで、ハンバーガーショップハンバーガーを買うシーンを想像してみてください。

  • お客さん「注文いいですか?」
  • 店員さん「店内でお召し上がりでしょうか?」
  • お客さん「持ち帰りで」
  • 店員さん「ご注文をお伺いします」
  • お客さん「チーズバーガーのセットで。飲み物はコーラでお願いします」
  • 店員さん「お支払い方法はどうされますか?」
  • お客さん「Suicaで」

実際の店舗で行われるやり取りの基本です。このやり取りをそのまま画面に置き換えると、最初の画面は「店内or持ち帰りを選択する画面」になるはずです。この本を読んだ後、飲食店の券売機やオンライン注文を実際に利用してみました。

牛丼チェーンはテイクアウト不可の商品もあるので、最初に「店内で食べるか」を選択させたいのは理解できます。決済する段階まで進んだ後に「この商品はテイクアウト不可」ですと言われたらムッと来ますからね・・。

ですが、ピザを注文する時に「配達」か「持ち帰り予約」を最初に選択させられるのは納得いきませんでした。メニューを見たかったのですが、配達先の住所を入れ終わらないとメニューが表示されなかったのです。「配達」と「持ち帰り予約」の違いは割引があるかどうかだけなので、「まずはメニューを見せてくれ!」という気持ちでいっぱいでした。

読んでみた感想

自分のような「デザインを少しでも理解したい非デザイナー」には得るものが多い書籍でした。普段使っているアプリケーションの画面を見ている時も「このアプリの主要人物は誰だろう?」と考えるようになったので、自分の中での思考の変化を感じています。書籍の1/3は読者が画面を実際に作るパートになっており、この構成も理解を深める助けになっています。

一方で少しひっかかる箇所もありました。プログラミングやデータベース設計を比較例として挙げている頁があるのですが、非エンジニアの人には逆に伝わりにくくなっている印象です。エンジニア側の自分にはスッと入ってくる話でしたが、賛否が分かれるところだと思います。

PHPerKaigi 2021でDIの話をしてきました

phperkaigi.jp

3/26〜28の3日間で開催されたPHPerKaigiにCFPを通すことができたので登壇してきました。

今回のネタ

今回はDependency Injectionに焦点をあてて、今こそ理解するDI(Dependency Injection)というタイトルにしました。TimeTableを改めて見てみると、僕以外にもDIの話をされる方がいらしたので、そんな中で採択されたのはとても嬉しかったです。

テーマをDIにした理由

  • CakePHPにDIコンテナが実験的に導入されるにあたって、DIを正確に理解しておきたかった。
  • PHPに限定した話にしたくなかった。

理由は2つあります。

1つめはCakePHPにDIコンテナが実験的に導入されるにあたって、DIを正確に学んでおきたかったからです。

book.cakephp.org

僕は元々Java畑でプログラミングに入門した人間です。Seasar2やSpringを使ったこともあるので、自分でも知らないうちにDIを使っていたとは思うのですが、人に言葉で説明できるほどの理解をしていませんでした。なので、CakePHPにDIが実験的に導入されると耳にした時、学びなおすチャンスだと思ったのです。

2つめは広めなテーマで話をしたかったからです。

僕は去年のPHPカンファレンスではPHPに限定した話でCFPを通すことができました。

今こそ理解する PHPの日時計算 / Understand date manipulation of PHP - Speaker Deck

その流れに乗るつもりで、今回もPHPに限定した話でネタを練っていましたが、PHPに限定しない話をしたい気持ちもありました。特に設計やデザインパターンにまつわる話に興味があったので、DIはCFPのテーマとしてマッチしていたというわけです。

録画収録の感想

PHPerKaigiのトークは事前収録だったので、本番の2週間前には収録を終えていました。

枠は20分と決まっているので、20分ジャストで終われるように事前練習を何回かおこないました。初回の事前練習では、余計な小話をしたせいで26分程度かかっていましたが、話す内容を絞り、話す速度を調整することでなんとか形にできました。

個人的に意外だったのは、トークを事前に収録してあっても、本番で自分のトークが始まる前は緊張してしまうことでした。Ask the Speakerでちゃんと受け答えができるか不安だったんですかね・・?

まとめ

トークの準備はかなり大変でしたが、話す側でイベントに参加すると本当に勉強になりますね。Ask the Speakerの時間で理解を更に深められた気がします。

  • 「GoにはInterfaceがないが、InterfaceがないとDIはやれないのか?」
  • 「一般的なデザインパターン(Factory Method等)とDIの使い分けはどうすればいいのか?」

この辺りは自分の中でも新たな課題として残ったところなので、PHPerKaigiの登壇で満足せずに深堀りを続けていきます。

Amazon | Head First Design Patterns | Freeman, Eric, Robson, Elisabeth, Sierra, Kathy, Bates, Bert | Software Development

「Head First Design Patterns (リンクは2nd edition)」が参考文献としてすごく良いらしいんですが、632ページもあるうえに英語なので途中で挫折する気がしてなりません(´・ω・`)。

Amazon | Dependency Injection Principles, Practices, and Patterns | Seemann, Mark, Deursen, Steven van | Software Development

僕の登壇資料の根っこになっている「Dependency Injection Principles, Practices」も良書なんですが、日本語版がないので誰かに翻訳してほしいなって100回くらい思ってます。

PHP Conference Japan 2020 Re:bornに登壇してきました

phpcon.php.gr.jp

本日行われた、こちらのイベントに「今こそ理解するPHP日時計算」というタイトルで登壇させていただきました。 資料は発表前にSpeakerDeckにあげているので、そちらでご覧いただけます。

今こそ理解する PHPの日時計算 / Understand date manipulation of PHP - Speaker Deck

CFPが通った感想

正直言うと、CFPが通るとはあまり思っていませんでした。PHPの8系やcomposerの2系が出るタイミングでもあったので、セッションはそういった話題で埋まってしまうだろうと予想していたわけです。

予想に反してCFPが採択された時は、嬉しさ半分、驚き半分の気持ちでした。「こんな地味な内容で人が集まってくれるのかな・・?」という不安はあったものの、僕が過去に躓いたトピックが刺さる人は一定数いると考えることにし、資料作りに勤しみました。

準備にあたって意識したこと

  • 普段話をする時よりも、少しゆっくりめに話す。
  • 素振り(事前の1人リハーサル)を多めにやる。

今回は以上の2点を意識しました。

「オンライン配信で早口で話しすぎると、リスナー側が聞き取りにくいのでは?」と思い、本番では素振りをした時よりも少しゆっくりに話すことを意識しました。話すスピードを考慮して直前に内容を少しだけ削ったのですが、それでも1分半ほど時間をオーバーしてしまいました。タイムキーパーの方、すみません・・(´・ω・`)。

25分の枠で話すのも初めてだったこともあり、その感覚を掴むために予行演習もきっちりやりました。初回の予行演習は喋りに詰まってしまった上に説明も間延びしてしまい、正直聞けたものではなかったです。その後、自分の口から出た言い回しや説明をノートに書き出し、不要なものを削りつつ整理して本番に臨みました。

自分の録画を見返してみての感想ではありますが、70点くらいの発表には出来たんじゃないかと思っています。

オンラインのカンファレンスに参加した感想

聴衆側の観点でいうと、気軽に色んなセッションを覗きに行けるのが便利でした。オフラインだと、混みそうなセッションの会場に先に入っておいて待機するサイクルになりがちでしたが、オンラインなら会場の定員を気にする必要もないので楽です。

登壇側の観点でいうと、出番前の独特の緊張感が印象的でした。劇の出番を舞台袖で待つ役者はこういう気持ちなのかな・・とか考えながら待機していました。始まってしまえばスラスラ話せるものなんですが、登壇は何度やっても緊張するものですね。

discordを見ながら話すのは難しい

登壇時は、PCの脇に置いたiPadにdiscordの画面を映しながら喋っていました。コメントに対するリアクションを交えながら話すつもりでしたが、実際はそこまでの余裕がなくて歯がゆい思いをしました。

合間でコメントに反応する前提で話すなら、スライドの量もそれに応じて調整した方がよかったかもしれません。

まとめ

準備はそれなりに大変でしたが、参加して本当に良かったと思います。スタッフの方々の手厚いサポートもあって、不安の少ない登壇経験が出来た気がしています。本当にありがとうございました。

カンファレンスのCFPが正式に採択されたのも今回が初めてで、個人的にも一歩前進できて本当に嬉しいです。

会社のちょっとした宣伝

connehito.connpass.com

今週末の12/17(金)には自社のミートアップがあります!「サービス開発のあるある話」などをしつつ、会社を跨いだ交流が目的のイベントです。 興味のある方は是非ご参加ください〜〜!