教材を通してやってみたこと
- 教材通りにやってみる
- セクションごとに新しいブランチを切って、別の書き方を試したり、エラーを解消したりする
(教材どおりにやるとコンソールにwarningやerrorが出ていたのが気になったので...)
身についたこと
- 関数コンポーネントの記法
- 親と子の同期
- useState, useCallback, useEffectの基本的な使い方
- (関数コンポーネントにおける)レンダリングの仕組みと無駄なレンダリングを減らす方法
- GitHub Pagesのdeploy
- ファイルの分割&整理
まだ知りたいこと
- useMemoなどその他のHook, クラスコンポーネントの基本的なところ
- 関数型プログラミング
- 配列の操作がやっぱりまだ苦手。。
はまったところ
setStateでsnakeの位置やfieldsを別々に更新すると複数回のレンダリングになるのでは...?
と思って他の方法はないのかな〜と調べてuseReducerに行き着く。
公式読みながら、ググりながらやってみる。けど、どうもうまくいかない。。
▼そのときのチケット
https://ticketnote.dev/ticket/sd2phLyC52LZgHh8sOb8
わかったこと
コードをいじり、検証しまくり、辿り着いたのが
「1回のdispatchでreducerが2回呼ばれてる」 → 新しいエサが2個出現してる
これはstrictモードを外したら解消された!(3日くらいこれで悩んでた)
▼参考にしたツイート
https://twitter.com/takeshy/status/1286119058744598528
多分、reducerの中で新しいエサを作る処理とか、書き方自体がダメだったんだろうな。。
やってみたこと
reducerの中でやる処理を減らして、action.payloadで新しいエサの位置などを引っ張ってくる。
reducerが複数回呼ばれても問題ないようにする。
で、できた!↓
https://github.com/Fielsyuka/hooks-snake-game/blob/section05-re-fix/src/App.js
よくわからないこと
下記のようにreturnする前にstateをコピー&編集してreturnするのはOKなのかNGなのか・・・?
問題なく動いてるけど合ってるのかよくわからない。。
case "newFood":
const newFields = [...state.fields];
newFields[action.nextPos.y][action.nextPos.x] = "snake";
newFields[action.nextFood.y][action.nextFood.x] = "food";
return {
body: newBody,
food: action.nextFood,
fields: newFields,
};
完成したもの
Github Page
https://fielsyuka.github.io/hooks-snake-game/
Git
https://github.com/Fielsyuka/hooks-snake-game