React + TypeScript学習ログ
create-react-app
)
導入(% npx create-react-app my-app --template typescript
Need to install the following packages:
create-react-app@5.0.1
Ok to proceed? (y) y
npm WARN deprecated tar@2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.
Creating a new React app in /Users/**/my-app
Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template-typescript...
added 1394 packages in 39s
209 packages are looking for funding
run `npm fund` for details
Initialized a git repository.
Installing template dependencies using npm...
added 35 packages, and changed 1 package in 2s
209 packages are looking for funding
run `npm fund` for details
We detected TypeScript in your project (src/App.test.tsx) and created a tsconfig.json file for you.
Your tsconfig.json has been populated with default values.
Removing template package using npm...
removed 1 package, and audited 1429 packages in 1s
209 packages are looking for funding
run `npm fund` for details
6 high severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
Created git commit.
Success! Created my-app at /Users/**/my-app
Inside that directory, you can run several commands:
npm start
Starts the development server.
npm run build
Bundles the app into static files for production.
npm test
Starts the test runner.
npm run eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!
We suggest that you begin by typing:
cd my-app
npm start
Happy hacking!
ベストなディレクトリ構成とかある?->公式としてはない。
考えすぎない
まだプロジェクトを始めたばかりなら、ファイル構成を決めるのに 5 分以上かけないようにしましょう。上述の方法の 1 つを選ぶか、自分自身の方法を考えて、コードを書き始めましょう! おそらく実際のコードをいくらか書けば、なんにせよ考え直したくなる可能性が高いでしょう。
ルーティングしたい->React Routerを導入しよう
React Router公式
使い方参考
POSTリクエストを送りたい(非同期HTTP通信したい)-> useState + Axios
それぞれの担当範囲
- useState:フォーム入力値の取得
- Axios:HTTPリクエスト
useState使用法参考
Axios公式
Axios使用法参考
他の候補
react-error-boundary
を導入しよう
包括的にエラーハンドリングしたい->前提
React純正のerror-blundary
機能ではキャッチできないエラーがある。
error boundary は以下のエラーをキャッチしません:
- イベントハンドラ(詳細)
- 非同期コード(例:setTimeout や requestAnimationFrame のコールバック)
- サーバサイドレンダリング
- (子コンポーネントではなく)error boundary 自身がスローしたエラー
全部まとめてキャッチしたいなら、react-error-boundary
。
GitHubページ
使い方参考記事
外部リソースのデータを取得して表示したい->useState + useEffect + Axios
それぞれの役割は以下の通り
- Axios:HTTPリクエスト(GET)によるデータ取得
- useState:Axiosが取得したデータの保持
- useEffect:レンダリング後に処理を実行する
非同期処理の成功・失敗の確定後にエラーハンドリングしたい -> Suspense機能
やろうとしたこと
- useEffect内でリストを取得する非同期処理(GETリクエスト)
- 取得したリストから指定の要素を検索(Array.find())
- 要素の有無を判定。結果に応じて表示を変える
- 指定の要素がある -> 通常画面表示
- 指定の要素がない -> エラーを投げる
- エラーは前述の
react-error-boundary
にキャッチされ、エラーページが表示される
- エラーは前述の
直面した課題
非同期で指定の要素を取得しようとしているため、3の判定のタイミングでは必ずfalseになり、エラーページへ遷移してしまう
実現したいこと
- 要素有無の判定処理を非同期処理完了を待ってから実施したい
試したこと
useLayoutEffectフック -> 失敗
useLayoutEffectは処理実行タイミングが、useEffectより早い。
useLayoutEffectで非同期処理を実施し、useEffectで判定を行う
結果:useEffectはuseLayoutEffectの実行完了を待ってくれるわけではないため、非同期処理が長引けばエラーとなる。
useEffect(useLayoutEffect)フックの第二引数を使う -> 失敗
第二引数を指定することで、処理を実行するタイミングを非同期処理完了後にする
結果:レンダリング時の初回実行を避けられず失敗
Suspense機能を使う -> 成功
Suspense機能とは?
- React 18に備えるにはどうすればいいの? 5分で理解する - Qiita
-
ReactのSuspense対応非同期処理を手書きするハンズオン
->非同期処理中に待機して代わりのJSXを表示してくれるイメージ
これで非同期処理を管理し、完了後に判定処理を実施する形で実装。
結果:参考記事をもとに実装し、どうにか成功。理解は浅いのでもっといい書き方がありそうな気がする。
参考
アプリ全体で、最新のステートを共有したい -> useState + proprs + React.FC
- 一番の親コンポーネント(Appとか)でuseState宣言
- 子コンポーネントにプロパティとして渡す
- TypeScriptの場合、ちゃんと型定義していないとここでエラー
- 型エラーが発生したらコンポーネントに
React.FC
型を宣言する。 -
function
でコンポーネントを定義していたりするなら、書き換えのためにここでconst
による定義に変更する。
※functionによる定義というのは以下のようなやり方
function App () {
return <div>...</div>;
}
上記をconstで定義するやり方に直すと以下のような感じになる。
const App = () => {
return <div>...</div>;
}
propsとしてステートをやりとりするにはさらにReact.FC
型をつけて以下のような感じにする
※<Child>
は子コンポーネントを表す
const App: React.FC<{ props: **propsの型** }> = ( props ) => {
return <Child props={props} .../>;
}