🦁

ポケモンと共に React を学ぶ

チームメンバー並びに社内のエンジニアの力を底上げするため React 教育にあたって、今回作成したドキュメントサイトを補足する内容となっています。

By jiyuujin at

#React
#TypeScript
#Pokemon-API
#Vercel
#VuePress
ポケモンと共に React を学ぶをはてなブックマークに追加

React ハンズオンの企画

もとは、あまり React を触ったことのない方へ向け教育用リポジトリを作成しました。

今回は、プロジェクトに限り知見を発信させていただいております。

詳細は下記ウェブサイトを見ていただきます。

Pokemon アプリ | Hack React

そもそも React で Hooks を使って書くのが今の流行りで、コンポーネントを書く際、クラスコンポーネントと関数コンポーネントに分けられる。

今回扱った教材の Hooks API は後者の範疇に入る。

Hooks 導入以前まで、関数コンポーネントに state を持たせられなかった代わりに state を持たせるためクラスコンポーネントを実装する他なかった。

関数コンポーネントを使うべき理由

主な理由を下記の通り。クラスコンポーネントでは this を用いて state を参照しなければいけず、更新する際も state に this を用いて参照しなければいけない。

  • this を使う必要が無くなる
  • メソッドを bind する必要が無くなる
  • 初期化する constructor を書く必要が無くなる

クラスコンポーネント

クラスコンポーネントの例。

class Example extends React.Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
    this.handleCount = this.handleCount.bind(this)
  }

  handleClick() {
    this.setState({ count: this.state.count + 1 })
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={this.handleClick}>+1</button>
      </div>
    )
  }
}

関数コンポーネント

関数コンポーネントの例。

const Example = () => {
  const [count, setCount] = React.useState < number > 0

  function handleClick() {
    setCount(() => count + 1)
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>+1</button>
    </div>
  )
}

今回のゴールである Pokemon API をフェッチして Vercel へのデプロイを果たした。

Hack Pokemon

今回はフェッチと検索を扱う

目標を Hooks API をベースとした Web アプリケーションを作ることとした。今回のターゲットを考慮して、フレームワーク Next.js を一切使わない選択をとった。

その目標を達成するため複数の技術的なマイルストーンを合わせ準備している。

  • useSWR を利用して API をフェッチする
  • useState を利用した状態管理
  • useMemo を利用した再描画の仕組み

今回は状態管理やユニットテストを扱っていない。次回以降、この辺りを中心にテーマを選定したい (ご気軽に Issue や PR ください)

jiyuujin/hack-react

状態管理で別の手段 useEffect も存在する

API のフェッチを useEffect で行い state を useState で管理する方法も存在する。

const [pokemonData, setPokemonData] = React.useState<Array<{ name: string; url: string }>>()
React.useEffect(() => {
    const data = fetch(`https://pokeapi.co/api/v2/pokemon?limit=200&offset=200`)
    setPokemonData(data.results)
}, [])

{/*読み込み中*/}
if (!pokemonData) return <div>Loading..</div>

{/*読み込みに成功した*/}
return (
    <React.Fragment>
        {pokemonData?.map((pokemon: { name: string; url: string }) => (
            <div key={pokemon.name}>
                {pokemon.name}
            </div>
        ))}
    </React.Fragment>
)

useSWR を使うか useEffect を使うのは各プロジェクトの設計方針により決定しましょう。

ポケモンと共に React を学ぶをはてなブックマークに追加