React を使ったポートフォリオサイトを作成してみた

# はじめに

React を学習していくにあたり、これからの成果物を掲載していくポートフォリオサイトを作成しました。Atomic Design の考え方を参考に、コンポーネントを意識しながらのサイト作成は、React の技術だけでなく、サイト設計の考え方、html、css の書き方についても改めて気づくことの多い経験となりました。

# デザイン

今回は AdobeXD を利用してデザインを作成しました。
デザインをする機会はめったにないので、まずはショートカットキーを中心に操作方法から学びます。操作方法は Udemy の下記講座を参考に基本的な使い方を学習しました。

https://www.udemy.com/course/adobe-xd-uux/

デザインのイメージについては[nicepage](https://nicepage.com/html-templates)というテンプレートサイトからイメージにあうデザインを検索し、最終的に下記テンプレートを参考にさせていただきました。

https://nicepage.com/t/255570/web-developer-portfolio-template

上記デザインを参考にしながら試行錯誤を 1-2 日繰り返して出来上がったデザインがこちら。
![design.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268181/3919e5ff-b410-c51f-5938-9286e03c9854.jpeg)
色々と発想を切り替えようとはしましたが、デザイン時にコンポーネントを意識したり、コーディングの再現性を考えてしまうとなかなか思い切ったデザインにするのは難しいと感じました。。。早速今後の大きな課題です。

# Atomic Design とコンポーネント設計

デザイナーである Brad Frost 氏の UI 設計に基づいたデザインシステムのこと。デザインパーツを 5 つの分類に分けて構造構築していくということのようです。この形が Atomic Design であるという正解を見出すことは難しいようですが、Atomic Design の思想を参考に、コンポーネント設計していこうというのが今回の目的です。

https://atomicdesign.bradfrost.com/

- **Atoms（原子）**・・・ボタン、アイコン、インプットエリアなどの要素の最小単位。
- **Molecules（分子）**・・・Atoms の集合体、アイコン付きのボタンや検索ボックスなど。
- **Organisms（有機体）**・・・Atoms、Molecules の集合体。ヘッダーや検索エリアなど。
- **Templates（テンプレート）**・・・Organisms の集合体。ページレイアウトなど。
- **Pages（ページ）**・・・表示するページそのもの。

作成したデザインを Atomic Design を想定したコンポーネントに分割していきます。今回は 1 ページものということもあり最終的には Template は作成しませんでした。
![atomic.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268181/9ba94c98-b924-4380-c506-ef1cbb980ae9.jpeg)

# Storybook をちょいかみしながら、なんとなくのコンポーネント駆動開発

コーディングにあたっては、一度使ってみたかった Storybook を利用して、コンポーネント駆動開発的なものに挑戦しました。

コンポーネントを考えてサイト制作をすることで、表示とロジック部分の分離や、パーツの流用、更新など保守に強いサービスを作っていくことができます。チーム開発でのイメージがありましたが、今回体験してみて個人開発でも当たり前のように必要な考え方なのだと知ることができました。

使用方法が全く未知数だったので、公式のチュートリアルと下記動画で触りを学習してから構築を行いました。v5 と v6 で大きく変わっていることもあり、ネットの情報も注意しながら取捨選択していきます。

https://youtu.be/BySFuXgG-ow

途中何度も挫けそうになりながら毎日少しずつ少しずつコンポーネントを作成していきます。
部品はなんとなく出来上がっていきますが全体がどうなるかが未知数のまま進むので不安が募ります。。
その分、最後に一つの Pages に Organisms たちを設置、突然デザインのページが出来上がったときにはちょっとした感動を覚えました。
![storybook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268181/b8693109-10c6-29d1-0785-a29bec0bdeff.png)

今回各コンポーネントは CSS modules を利用して設計しましたが、ロジックによって props を渡して style を変更したい時など、クラス名を当てたい時に不便さを感じました。CSSS modules だと通常のhtmlコーディングと同じような思想で書くことができるので書きやすくはありますが、今回のようにコンポーネントを小さく分けていく場合は styled-components が使いやすそうだと感じました。次の開発では styled-components または emotion を利用して試してみようと思います。

# ロジックの組み込み

今回のロジックを組んでいくにあたって、あえて props drilling を経験してみるという謎のテーマで進めていきます。
React を学び始めたのが最近ということもあり、学習当初から Context や Redux、その他状態管理の情報が豊富にあるので props をバトンし渡していくということの理解がいまいち足りていないと感じていたからです。もちろん、そのおかげでこの先もたくさん苦労することとなりましたが。。

モダール部分はライブラリは使わずに、CSS と Hooks を利用して設置、CONTACT 部分は React Hook Form を使って実装を行いました。

https://reffect.co.jp/react/react-modal

https://react-hook-form.com/

# Amplify との連携

サイトを Amplify にデプロイするにあたって、またここで新たに欲が出てきます。
PORTFOLIO 一覧部分は、制作当初は json ファイルから出力をしていたのですが、GraphQL を試してくなり、最終的に AppSync を利用して DynamoDB のデータを出力する形に。
CONTACT フォームもダミーで済ませようとしたところから、API Gateway、Lambda を利用して、SendGrid から送信と 1 日、また 1 日と、3 歩進んで 2 歩下がる日々が続きました。。。

今回初めて Amplify を使いましたが、裏で何が動いているかわからず、問題が起きても解決方法がなかなか見えない、何がわからないかわからない事態が 2 日程度続いたので、ポートフォリオサイト作成の中、この部分が一番苦労したところかもしれません。

https://dev.classmethod.jp/articles/react-amplify-appsync-dynamodb-tutorial/

# リリース

デザイン着手から 2 週間程度かかりましたが、なんとか世に公開することができそうです。
内容がまだ何もないので、これからは掲載していく作品数を増やすべくさらなるステップアップを目指します！

# さいごに

デザインからデプロイまでを経験することで、はまりどころたくさんあり何度も遭難しかけましたが、ひたすら調べる、試すの繰り返しでなんとかまとめきることができました。自分にとってこの 2 週間という時間以上にとても大きな経験を積むことができたと感じています。今まではインプット中心で学習を続けてきましたが、こういったアウトプットできるものを作ることで大きな一歩を踏み出すことができました。

# 関連記事

https://qiita.com/himorishige/items/31e7f45e7598ccda9f52

https://qiita.com/himorishige/items/8c1b54dfca2bb074668b

# 参考サイト

**Design**

https://www.udemy.com/course/adobe-xd-uux/
 
https://nicepage.com/t/255570/web-developer-portfolio-template

https://atomicdesign.bradfrost.com/

**CSS**

http://kachibito.net/useful-resource/angled-edges

**Modal**

https://reffect.co.jp/react/react-modal

**Intersection Observer**

https://ryusou.dev/posts/react-intersection-observer

**Form**

https://react-hook-form.com/

**Storybook**

https://storybook.js.org/

https://youtu.be/BySFuXgG-ow

**Amplify**

https://qiita.com/rubytomato@github/items/5d9b6e184b615f974f28

https://dev.classmethod.jp/articles/react-amplify-appsync-dynamodb-tutorial/

**SendGrid**

https://sendgrid.kke.co.jp/