0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React - The Complete Guide (incl. Next.js, Redux) Day 3

0
Last updated at Posted at 2026-07-07

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 を有効に

image.png

what caused this update? が出る。便利

image.png

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 など)を組み合わせた処理を、再利用できるようにまとめた関数
というのがカスタムフックです。

受け取るときに名前を変える

fetchedDatauserPlaces に変える例。コロンの後が新しい名前。

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 だけ更新

となり、お互いに影響しません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?