No.
2022-03-07
  • Jan
  • Feb
  • Mar
  • Apr
  • May
  • Jun
  • Jul
  • Aug
  • Sep
  • Oct
  • Nov
  • Dec
  • Sun
  • Mon
  • Tue
  • Wed
  • Thu
  • Fri
  • Sat
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

やったこと

reactのmapでkeyにindexを渡す危険性について

Index as a key is an anti-pattern

Index as a key is an anti-pattern

このサイトのdemoがめちゃくちゃわかりやすい!
DEMO

keyにindexを渡してもいい条件

  1. 配列とその中の要素が静的(計算も変更もされない)
  2. 配列の中の要素がidを持ってない
  3. 配列がreorderやfilterされることが絶対ない

useMemoとuseCallbackの違い

useCallback vs useMemo

The React docs say that useCallback:

Returns a memoized callback.

And that useMemo:

Returns a memoized value.

In other words, useCallback gives you referential equality between renders for functions. And useMemo gives you referential equality between renders for values.

useCallbackもuseMemoもどちらもreferential equalityで評価される。

Since JavaScript has first-class functions, useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

JSは第一級関数なので

useCallback(fn, deps)
useMemo(() => fn, deps)

は等価である

So what is the difference?

useCallback returns its function uncalled so you can call it later, while useMemo calls its function and returns the result.


function foo() {
  return 'bar';
}

const memoizedCallback = useCallback(foo, []);
const memoizedResult = useMemo(foo, []);

memoizedCallback;
// ƒ foo() {
//   return 'bar';
// }
memoizedResult; // 'bar'
memoizedCallback(); // 'bar'
memoizedResult(); // 🔴 TypeError
const fetchUser = async () => {
  const res = await fetch(
    `https://jsonplaceholder.typicode.com/users/${userId}`
  );
  const newUser = await res.json();
  setUser(newUser); // 🔴 setState triggers re-render
};

useEffect(() => {
  fetchUser();
}, [fetchUser]); // fetchUser is a new function on every render

上記のようなコードがあったときにこれでは、毎回useEffectが実行されてしまう。

理由としては、毎回fetchUser関数が新しい参照先で生成されるから。

解決策1

// 1. Way to solve the infinite loop
useEffect(() => {
  const fetchUser = async () => {
    const res = await fetch(
      `https://jsonplaceholder.typicode.com/users/${userId}`
    );
    const newUser = await res.json();
    setUser(newUser); // Triggers re-render, but ...
  };

  fetchUser();
}, [userId]); // ✅ ... userId stays the same.

useEffectの中に閉じ込める

解決策2

// 2. Way to solve the infinite loop
const fetchUser = useCallback(async () => {
  const res = await fetch(
    `https://jsonplaceholder.typicode.com/users/${userId}`
  );
  const newUser = await res.json();
  setUser(newUser);
}, [userId]);

useEffect(() => {
  fetchUser();
}, [fetchUser]); // ✅ fetchUser stays the same between renders

useCallbackを使用する