ref https://www.udemy.com/course/react-the-complete-guide-incl-redux/learn/lecture/40270524#overview
高速化とか最適化の話に入ってきた
memo
how to use the react debug extension
memoを理解するのに必要
Record why each component rendered while profiling を有効に
what caused this update? が出る。便利
memo はpropが変わってないのにre-renderされるのを防ぐ
親が変わると子供もrenderされる
memoはpropsが同じならrenderしなくなる 子供もrenderされるのを防ぐ
memoが効かない場合に useCallback
親から渡される関数は親がrenderするたびに違うobjectになる
それをpropsでchildに渡すと、違うものになるので memo が効かない
useCallbackを使うと同じobjectに維持できるっぽい
useCallbackの中って無名関数だったっけ
const handleIncrement = useCallback(function handleIncrement(){
setCounter((prevCounter) => prevCounter + 1);
}, []);
<IconButton icon={PlusIcon} onClick={handleIncrement}>
こう書いても同じ
const handleIncrement = useCallback(() => {
setCounter((prevCounter) => prevCounter + 1);
}, []);
useMemo は normal functions の memo
memo は component 用
useMemo は 関数用。function cacheと思えばいいかも。
function isPrime(number) { ... }
const initialCountIsPrime = useMemo(() => isPrime(initialCount), [initialCount]);
実は useCallback は内部的には useMemo の糖衣構文のようなものです。
useMemo
毎回計算したくない値を保持します。
useCallback
毎回新しい関数を作りたくない場合に使います。
| Hook | キャッシュするもの | 返り値 |
|---|---|---|
useMemo |
計算結果 | 何でも(値・object・配列・関数) |
useCallback |
関数 | 関数 |
key
keyを固定したいとき
keyにindex与えてるとlistが変わった時にずれてcomponentが持つkeyが変わる。これを固定したいときは Math.random() * 100 を当てる. 100 は、まあそれ以上あっても衝突しないやろ、のかず。
key resets components
useEffect は無駄になることが多い renderの後に実行されるから
keyが変わるとcomponentは強制的に作り直される。これを利用してcomponentをresetして初期化させる方法がある
as-is
<Counter initialCount={chosenCount} />
to-be
<Counter key={chosenCount} initialCount={chosenCount} />
Million.js すごそう
- React の Virtual DOM のオーバーヘッドを減らし、DOM を直接・最小限更新するライブラリ。
- 静的な DOM 構造を解析し、動的な部分だけを書き換える。
- 例:
<p>{count}</p>は更新時にtextNode.data = countだけ実行。 - 大量のリスト・テーブル・ダッシュボードなどで効果が大きい。
- React API をそのまま使えるが、Babel/Vite Plugin などで最適化を行う。
- React の内部実装に近い部分を利用するため、React の更新への追従が必要。
- 複雑な JSX や動的な構造は最適化できず、通常の React にフォールバックすることがある。
- デバッグやライブラリ互換性の調査は React 単体より難しくなる場合がある。
- 利用者が少なく、情報や事例は React より少ない。
- 一般的な業務アプリでは React Compiler で十分なケースが多い。
- Million.js は「React でも足りないほど描画性能が重要な場面」で採用を検討するライブラリ。
chain methods はもう古い
知らなかった
JavaScript全体としては、async/awaitの登場以降はPromiseチェーン(.then().then())を書く機会はかなり減りました。
ただし、「好まれなくなった」というよりは、
逐次的な非同期処理を書くならasync/awaitの方が読みやすい
という評価になっています。
good:
const response = await fetch(url);
const data = await response.json();
const user = await getUser(data.id);
not good:
fetch(url)
.then((response) => response.json())
.then((data) => getUser(data.id))
.then((user) => {
// ...
});
一方で、Promiseチェーンが今でも適している場面もあります。
例えば、単純な変換をつなげるだけなら、は十分読みやすいです。
fetch(url)
.then((r) => r.json())
.then(process)
.then(render)
.catch(handleError);
なるほどなぁ
async/awaitが増えた理由: async/awaitが使いたいというより、promiseを返す関数が増えた
例えば fetch(). 非同期通信をする前提の関数だから Promise が帰ってくる。fetchを使いたいなら、awaitするしかない。javascript標準関数が、もうpromise前提になってるのだ。
async/awaitが必要なのではなく、Promiseを扱う必要があるからasync/awaitを使ってるのだ。
これは長年の謎が氷解した気分。
useEffectのコールバック自体はasyncにできません。
❌
useEffect(async () => {
// ...
}, []);
これは useEffectがクリーンアップ関数または何も返さない関数を期待している ためです。
Custom Hooks
use から始まるものは hooks というルールがある
custom hooksというのは、いったん useEffect() を使う関数を外出しするものと思っているとよさそう。汎用的なものにするといいみたい。例えば isLoading などを持つ fetch functions.
import { useRef, useState, useCallback, useEffect } from 'react';
export function useFetch(fetchFn) {
const [isFetching, setIsFetching] = useState(false);
const [error, setError] = useState();
const [fetchedData, setFetchedData] = useState();
useEffect(() => {
async function fetchData() {
setIsFetching(true);
try {
const data = await fetchFn();
setFetchedData(data);
} catch (error) {
setError({ message: error.message || 'Failed to fetch data.' });
}
setIsFetching(false);
}
fetchData();
}, [fetchFn]); // <---- 関数が変わったら再実行
return {
isFetching,
fetchedData,
error,
};
}
実際には useEffect がなくてもカスタムフックは作れます。より正確には
React Hooks(useState、useEffect、useMemo、useCallback、useContext など)を組み合わせた処理を、再利用できるようにまとめた関数
というのがカスタムフックです。
受け取るときに名前を変える
fetchedData を userPlaces に変える例。コロンの後が新しい名前。
const { isFetching, error, fetchedData: userPlaces } = useFetch(fetchUserPlaces);
Form
htmlFor
<label htmlFor="password"> は <label for="password のこと
for
<div class="preference">
<label for="cheese">チーズが好き</label>
<input type="checkbox" name="cheese" id="cheese" />
</div>
この値は、同じ文書内のラベル付け可能なフォームコントロールの id であり、この をそのフォームコントロールに関連付けます。なお、 JavaScript が反映するプロパティは htmlFor です。
https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/label
input id と label for がひもづく。こんな基礎すら忘れていた。
new formData()
preventDefault 懐かしい。
function handleSubmit(event) {
event.preventDefault(); // deactivate the default form submission behavior
const fd = new FormData(event.target); // create a FormData object from the form
const place = fd.get('place'); // get the value of the input field with name 'place'
console.log(place); // log the value to the console
}
return (
<>
<form onSubmit={handleSubmit}> <!-- <-- `event` を送る
<input id="place" type="text" placeholder="Enter a place" />
</form>
</>
);
new FormData(event.target) でなんかええオブジェクトが作られる。 .get() で値が取れる。
fd.entries()
newFormData.toEntries() がこれやればいいのにと思ってしまった
const fd = new FormData(event.target); // create a FormData object from the form
const data = Object.fromEntries(fd.entries()); // convert FormData to a plain object
console.log(data); // {name: "John Doe", place: "New York"}
useActionState
formState に action={func} の return が入る。
useActionStateってページ内に複数の
があったらどうなるの?useActionState に渡す1st argがどの form action かどうかで紐づく。
function Page() {
const [profileState, profileAction] = useActionState(updateProfile, null);
const [passwordState, passwordAction] = useActionState(updatePassword, null);
return (
<>
<form action={profileAction}>
<input name="name" />
<button>プロフィール更新</button>
</form>
<form action={passwordAction}>
<input name="password" type="password" />
<button>パスワード変更</button>
</form>
</>
);
}
この場合、
- 上のフォームを送信 → profileState だけ更新
- 下のフォームを送信 → passwordState だけ更新
となり、お互いに影響しません。

