🏃

フロントエンド初心者が勉強を兼ねて簡易ポケモン図鑑を作った

2023/12/23に公開

はじめに

個人の意見が入ってますので「そうなんだ」くらいの温度感で読んでいただけますと幸いです🙇

成果物

https://pokemon-react-app-pink.vercel.app/pokemons

一覧ページ

詳細ページ

作った背景

仕事でフロントエンドに挑戦したかったためです。
「やりたいです!勉強してます!!」だけではなかなか挑戦させてもらえなかったので目でわかる事実を作ろうと思いました。
実務で使ってる技術を選び、コードの書き方も真似しました。

使った技術

1.TypeScript

会社で使ってる

2.React.js

会社ではNext.jsを使っているのですが、あえてReact.jsにしました。

理由は「今回作るものに対してNext.jsがオーバースペックと判断したため」です。
簡単なSPAが作りたいのでNext.jsを使ったとしても機能を使いこなせないと思いました。必要最小限で良いと思いますのでフレームワークでなくライブラリのReact.jsを採用

3.ChakraUI

自分が仕事していて一番よくみるUIライブラリです。
「CSSナンモワカラン」な人でもいい感じのUIが作れるので自分は好きです。CSSが一番苦手

4.PokeAPI

ポケモンの情報が取得できるAPIです。一般に公開されています。RESTとGraphQLで公開されているのですが、今回はRESTを採用しました。
自分でAPIから作ると時間がかかるので公開されてるAPIを利用してフロントエンドの実装に集中しようと思いました。
https://pokeapi.co

5.Vercel

デプロイのために使いました。
実務ではフロントデプロイはAmplifyを使うことが多いのですが、今回はデプロイでなくフロントエンドのプログラミングに焦点を当てたかったので気軽に使えるVercelにしました。

どのくらいで作ったのか

1ヶ月でひとまず形にしてデプロイしました

初心者なりにやってみたこと

1.UIライブラリの使用

UIライブラリは偉大です。使った技術のところでも紹介しましたが、本当便利です。
「CSSから勉強しよう」とするのも悪くないのですが、それをするとモチベーションの維持が難しいと考えました。なのでUIライブラリを採用しました。

まぁ、「会社で使ってる技術に触れたい」というのが一番の要因でしたが... 笑

2.過剰な技術を選定しない

使いこなせないもの使う必要のないものは基本採用しませんでした
Next.jsがそうです。また、APIとの接続にはfetchを使いました。周りの人に「RTKQueryとかあるよ」と教えていただき勉強してみましたが、少し過剰な気がします。fetchを難しく書かされてる感覚になったためです。なので状態管理ライブラリは使ってません。

3.ディレクトリ構成を考えてみる

src配下は下記の通りです

src
├── App.css
├── App.test.tsx
├── App.tsx
├── components ← コンポーネント
│   └── CardUI.tsx
├── hooks ← カスタムフック(ロジック)
│   ├── get-pokemon.ts
│   └── get-pokemons.ts
├── index.css
├── index.tsx
├── logo.svg
├── pages ← ページ
│   └── pokemon
├── react-app-env.d.ts
├── reportWebVitals.ts
├── setupTests.ts
└── types ← 型
    └── Pokemon.ts

コンポーネントを作ってみる

ポケモン一覧を表示する際、各ポケモンを表示する部分のカードUIコンポーネントを作ってみました。

描画とロジックの分離

ロジックをhooksというディレクトリに分けました。
今までReact.jsを書くときは一つのjsxに描画とロジックを混ぜていました。そのせいでテストがしにくい実装になっていました。テストのしやすさを考慮し分離をしました

// ポケモンの情報を取得するロジック
// 取得してる間はローディングし、取得し終わったらローディングをやめる
import { useEffect, useState } from 'react';
import { Pokemon } from '../types/Pokemon';

export const GetPokemon = (id: number = 0) => {
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const [pokemon, setPokemon] = useState<Pokemon>();

    const getPokemon = async (id: number) => {
        setIsLoading(true);
        const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
        const pokemon = await response.json();
        setPokemon(pokemon);
        setIsLoading(false);
    }

    useEffect(() => {
        getPokemon(id);
    }, []);

    return {
        isLoading,
        setIsLoading,
        pokemon,
        getPokemon
    }
};

今後どうする予定か

1.機能の追加/拡張

現状カントー地方のポケモンしか取得できません。ジョウト地方以降も表示もしたいです。絞り込み機能も欲しいですね。詳細ページも情報が少ないので工夫したいです。

また、ユーザーごとにお気に入りポケモンの登録などもできそうです。やれることはたくさんあるのでモチベーションと相談しつつひっそりと開発を続けたいです。

2.テストの導入

フロントエンドはたくさんテストの種類があるので試したい
優先度としてはロジックのテストをJestで導入したい

3.Reactの機能を使いこなす

Reactが持ってる機能を使いこなせていない気がします。
例えばfetchで外部APIのデータを取得する間のローディング、今はuseEffectを使っていますが、Suspenseを使うことでも実現できます
https://react.dev/reference/react/Suspense

力技で解決している部分をスマートにしていきます

やってみて

1.フロントエンドの楽しさを知る

UIを作るのは楽しいです。もちろんUIライブラリありきなのでフロントエンドエンジニアとしてもレベルは低いですが、もっとスキルを向上させたいです

2.実務でフロントエンド領域に関われるようになった

今まで2年ほどサーバーサイドの実装やインフラの設定しかできなかったです。
しかし、少しづつフロントエンドエンジニアさんと共通認識を持ちコミュニケーションが取れるようになりました。フロントのコードが読めるようになったというのが何よりの証拠です。

最近は軽微なフロントの実装や修正を担当できるようになりました。

3.サーバーサイド実装の質が上がった気がする

基本的に自分はWebAPIの実装を実務で行なっています。
今までは「とりあえずフロントが困らないような実装」や「『これってこの実装で良いですか?』とフロントエンドエンジニアに念入りなお伺いをしながら実装」が多かったです。

フロントへの関心が高まったことで「本当にこの実装が正しいのか。この方が良いのではないか」というのを自分だけで考えることが可能になり、今までより質の高い相談がフロントエンドエンジニアの方にできるようになった気がします。
具体的には「どうしたら良いですかね?」のコミュニケーションではなく「この方法で実装できそうなのですが、いかがでしょうか」という形のコミュニケーションができるようになりました。

まとめ

自分のできる領域が増えると楽しいです。引き続き小さな規模でフロントエンド開発を続けていきます

Discussion