LoLで出会ったプレイヤーを忘れないアプリを作った
ちょっと前にReact勉強のために作り始めて、その後、社内で勉強会のネタに使ったあとそのまま放置していたが、コードだけ整えて一旦公開することにした。
作ったもの
スラム街として有名なLeague of Legends(LoL)で出会ったステキ
なプレイヤーをメモとともに記録できるアプリ。
GitHub - Ryu-u/remember-that-guy
これから追加したい機能
- 本番対応
- 認証機能を追加して多人数対応
- 例外処理
今回の学び
react-exhaustive-deps
のwarning
副作用フックの利用法 – React useEffect
についてのこのセクションの補足に
もしも副作用とそのクリーンアップを 1 度だけ(マウント時とアンマウント時にのみ)実行したいという場合、空の配列 ([]) を第 2 引数として渡すことができます。
とあるので、てっきりuseCallback
の第2引数についても同じだと思ってたから、初回以降変わる必要のない値についてはuseCallback
の第2引数に[]
を渡していた。
ただ、そうすると、react-exhaustive-deps
が
React Hook React.useCallback has a missing dependency: 'setIsModalOpen'. Either include it or remove the dependency array react-hooks/exhaustive-deps
というwarningを吐くのでおかしいなと思ってたんだけど、リファレンスをよく読んだら、useCallback
の補足に
依存する値の配列はコールバックに引数として渡されるわけではありません。しかし概念としては、この記法はコールバックの引数が何なのかを表現しています。コールバックの内部で参照されているすべての値は依存の配列内にも現れるべきです
と書いてあった。
useEffect
とuseCallback
では第2引数の意味合いが少し違うのね。
ちなみに、useCallbackを使ったコードは
https://github.com/Ryu-u/remember-that-guy/blob/master/src/components/past-games/PastGames.tsx#L21
https://github.com/Ryu-u/remember-that-guy/blob/master/src/components/past-games/DescriptionModal.tsx#L22
この2箇所なんだけど、今考えてみるとどちらもuseCallback
を使う必要がなかった...。
あとで修正しておこう。
フロントエンドとバックエンドで使用パッケージを共有する
正直、これはSPAの本来の用途とはズレているはずであまりいい方法ではないと思う。 ただ、今回はcreate-react-appとExpressをTypeScriptを使って開発する際に、型をフロントエンドとバックエンドで共有したり、そもそもマイクロサービス的に複数のサーバーを組み合わせたりしないのでnode_modulesが2つに分かれるのが嫌だなと思って、使用パッケージを共有することにした。
(此処にVSCodeのキャプチャ)
この構成にするために工夫するところは3つある。
まずはpackage.json
"scripts": { "frontend-start": "BROWSER=firefox react-scripts start", "backend-start": "nodemon", "start": "ts-node --project tsconfig.backend.json backend/index.ts", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "heroku-postbuild": "yarn && yarn run build " }
frontend-start
でwebpack-dev-server
の立ち上げ。
backend-start
でnodemonを使って、バックエンドのソースを更新した時に自動でコンパイルを再実行させ流ような形でExpress起動(後述するがnodemonではyarn start
を実行している)。
他はcreate-react-appが作るものとかHeroku向けのコマンドとか。 Heroku向けのコマンドはまだ動かしてないので間違ってるかも。
次に、nodemonの設定はこういう感じ。
{ "watch": ["backend"], "ext": "ts", "exec": "yarn run ts-node --project tsconfig.backend.json -r dotenv/config backend/index.ts" }
バックエンド用のファイルを格納しているbackend/
ディレクトリを監視し、その中のソースが変更されたら再コンパイルする感じにしてる。
そして最後に、tsconfig.json
の設定。
今回はルートディレクトリにフロントエンド用のtsconfig.json
とバックエンド用のtsconfig.backend.json
を作成した。
tsconfig.json
を分けた理由は、フロントエンドとバックエンドでコンパイル後のJSのバージョンをフロントエンド→ES5、バックエンド→ES6という形にしたかったから。
それぞれのtsconfig.json
はこちら
# フロントエンド用tsconfig.json { "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "preserve" }, "include": ["src", "src/types"] }
# バックエンド用tsconfig.backend.json { "compilerOptions": { "allowSyntheticDefaultImports": true, "module": "commonjs", "esModuleInterop": true, "target": "es6", "noImplicitAny": true, "moduleResolution": "node", "sourceMap": true, "outDir": "dist", "baseUrl": ".", "paths": { "*": ["node_modules/*", "src/types/*"] } }, "include": ["backend/**/*"] }
正直重要なのがimport
を使うためのallowSyntheticDefaultImports
とesModuleInterop
くらいしかわかってないので、このあたりはまたどこかのタイミングでさいきょうのtsconfig.json
を書きたい。
所感
はじめは認証機能を追加するつもりはなく勉強だし一人用でいいやと思っていたのだが、思いのほか簡単に作れてしまったので、認証機能を追加しようと考え直した。
で、前から少し気になってたReactでのOAuth認証をやろうとしたところ、これが全くうまくいかない...
色々ググってみて紹介されているやり方を片っ端から試してみたが全然ダメ。
なので、これは後でまたチャレンジすることにして、コードだけ整えつつ今の状態で公開して一区切りつけることにした。
ReactでのOAuth認証は後でまた試して記事を書きたい。
あと、最近はLoLをやらなくなってしまった。