Next.jsで文字数制限の無いポケモンワードルを作った話

# はじめに
本記事はオフィスに猫がいる会社、株式会社qnoteの[アドベントカレンダー](https://qiita.com/advent-calendar/2022/qnote)7日目の記事となります。

いつもポケモンワードルで遊んでいるみなさまへ。

**5文字以外のポケモンも登場させてあげたいですよね？**

ということでNext.jsを使って**文字数制限の無い**ポケモンワードルを作ります。

# ポケモンワードルとは
5文字の英単語を推測して当てるWordleを参考に作られた、5文字のポケモンの名前を推測して当てるゲームです。
無限に遊べる神ゲーです。

[本家ポケモンワードル](https://wordle.mega-yadoran.jp/)
[作者様のTwitter](https://twitter.com/giga_yadoran)

# 今回作ったもの
5文字以外のポケモンも含め、全ポケモンが出題対象となるポケモンワードルです。
https://pokemon-wordle.vercel.app/
※本サービスで使用している情報や画像は[PokeAPI](https://pokeapi.co/)から取得したデータとなります。

![poke.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764219/c715734f-129d-9362-f094-dce9a96ef899.gif)

開発工数はトータル30〜40hくらいかかっていると思います。
ただ、初めてNext.js(React)を触った割にはサクサク作れた気がします。

# ざっくり解説
## 環境
Next.js:13.0.2
React:18.2.0
TypeScript:4.8.4
Tailwind CSS:3.2.0
Vercel

仕事ではVue.jsとLaravelをよく触っていますがReactは全く触れたことがなかったので、勉強のためにNext.jsを採用しました。

環境自体は↓から丸っとインストールできます。
https://create.t3.gg/

VercelはWebホスティングサービスで、Githubなどと連携すると自動デプロイまでしてくれる神サービスです。(Vercel Inc.という会社のサービスらしくNext.jsの開発元でもあるそうです)

## 機能
**・シリーズ選択(本家同様)**
本家同様にシリーズを選択できるようにしています。

**・特定のシリーズから新登場したポケモンのみ出題(オリジナル)**
こちらはオリジナルの機能で、初代は大体わかるけどダイパから新登場したポケモンはあまり覚えてないな・・・という人向けに作りました。
(~~筆者が初代、金銀、剣盾、とプレイしているにわかだったので自分の勉強用に入れたかった...~~)

**・出題文字数ランダム(オリジナル)**
全ポケモンを出題対象にして、ランダムに出題されたポケモンの文字数に応じて入力欄を動的に切り替えるようにしました。

**・シルエット表示(オリジナル)**
こちらもオリジナルの機能で、出題中にシルエット表示をする機能です。
開発中だけ表示するつもりだったのですが、シルエットクイズとしても楽しめるので残しました。
ポケモンマスターの皆様はシルエットを見ただけでほとんどわかってしまうと思いますが、アートワーク画像に切り替えたりするとまた違った楽しみ方ができると思います。
ちなみにCSSで通常の色付き画像をシルエット化しています。 
[参考：contrast() - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/filter-function/contrast)


**・画像表示切り替え(オリジナル)**
おなじみのドット絵とアートワーク画像を切り替えるようにしています。
ドット絵はいわずもがな素晴らしいですが、アートワークは初めて見るものが多くすごく惹かれる絵ばかりです・・・！

## 所感
**・とにかく作っていて楽しかった**
初めてNext.jsとReactを触り、これはどうすれば実現できるんだろう→調べる→実装する→動いた！の繰り返しで徐々にゴールに近づいていく感覚がとても楽しかったです。
こんな機能あったら良いな、と思いつきでオリジナルの機能を実装できるのも個人開発の魅力だなと思いました。

**・SSR、SSGの切り替えが簡単**
ビルド時に一度だけ情報取得する場合とリクエストごとに情報取得する場合と、切り替えがとても簡単でした。
こちらは↓の記事がめちゃくちゃわかりやすかったのでNext.js使いの方は必読です。
[参考：Next.jsにおけるSSG（静的サイト生成）とISRについて（自分の）限界まで丁寧に説明する](https://qiita.com/thesugar/items/47ec3d243d00ddd0b4ed)

**・オブジェクト、配列、二次元配列のState管理は罠！**
Reactの変数の変更検知はHooksのSetStateを使って行うのですが、Object.is()を使って判定している関係で、オブジェクトのアドレスが変わらないと再レンダリングされません。
スプレッド構文などで新しいオブジェクトを生成するとうまく再レンダリングされます。
更に二次元以上の配列になると浅いコピー(シャローコピー)と深いコピー(ディープコピー)を理解する必要があります。
[参考：浅いコピーと深いコピー](https://qiita.com/Tatamo/items/444969a7ff2fbba30479#%E6%B5%85%E3%81%84%E3%82%B3%E3%83%94%E3%83%BC%E3%81%A8%E6%B7%B1%E3%81%84%E3%82%B3%E3%83%94%E3%83%BC)


**・文字比較やStyle管理のアルゴリズムが意外とややこしかった**
入力された文字の中で緑判定、黄色判定された場合はそれ以降同じ文字があってもグレーになる、など細かい仕様があるので地味にややこしかったです。(正確には存在する文字数分しか色が変わらない)
また、文字入力欄とソフトキー1個1個のStyle管理が意外と大変でした。
こちらは現状二次元配列をいくつか用意して実現していますがもう少しスマートな方法がありそうです。

## 今後の課題
**・コードのリファクタリング**
主にコンポーネント設計をしっかりしたいです。
いまはゴリ押しコード満載です。

**・UI見直し**
他のサービスや本家ポケモンワードルと比べた時に、なんかださいな〜感が拭いきれずWebデザインも勉強しなきゃと思わされました。
なんかださい、のなんかを言語化できるようにしたいです。

**・Prismaを使ったDB連携**
今回はひとまずTypeScriptの定数でポケモンの情報を保持するようにしました。
今後はPrismaを使ってDBと連携して管理したいと思っています。
(Laravel以外のORMを触るのが楽しみ)

**・オンライン対戦の実現方法検討**
こちらはリリース予定はないのですが、本家ポケモンワードルはオンライン対戦が可能でどうやって実現しているんだろう、ととても興味があるので色々試行錯誤して作ってみたいと思っています。
**→こちら、なんと本家ポケモンワードルの作者様とやりとりさせていただくことがあり、情報交換させていただきました！感謝します！**

# さいごに
今回初めてReact,Next.jsを触りましたが、書籍を1冊読んだ程度でも比較的扱いやすく、やりたいことが簡単に実現できた印象があります。
コード整理が全くできていないのでコードの公開はしていないのですが、ある程度整理できたら公開しようと思っています。
また、ReactはVue.jsとは異なる書き方が多いですが、モバイルアプリ開発にて触っていたFlutterと、Hooksの考え方が似ていたので扱いやすかったです。

今後もポケモンワードルの改修や、その他個人開発を通して情報発信していきたいと思います！
最後まで読んでいただきありがとうございました！

# 参考情報
[本家ポケモンワードル](https://wordle.mega-yadoran.jp/)
[PokeAPI](https://pokeapi.co/)
[Next.jsにおけるSSG（静的サイト生成）とISRについて（自分の）限界まで丁寧に説明する](https://qiita.com/thesugar/items/47ec3d243d00ddd0b4ed)
[もう一度理解する、JavaScriptの配列とコピー](https://qiita.com/Tatamo/items/444969a7ff2fbba30479#%E6%B5%85%E3%81%84%E3%82%B3%E3%83%94%E3%83%BC%E3%81%A8%E6%B7%B1%E3%81%84%E3%82%B3%E3%83%94%E3%83%BC)