useCallback
以下は同じ
tsuseCallback(fn, deps);
useMemo(()=>fn, deps);
再描画時に deps
に前回と比べて変更があるとコールバックするfunctionを再編成する
考え方としては、fnの中で使う値を、depsに指定しておけばいい
ないとバグが起きる可能性が上がる
逆に「第二引数を使わない」ということはまずありえない
無意味だから。型エラーが出るので気付くはず
空配列はありうる
例
ts// returnFuncは関数になる
const returnFunc = useCallback(fn, deps)
deps
に変更があるとそのureturnFuncが新しく生成される
FC内で定義された関数は、FCが再レンダリングされるたびに新しいものになる
そもそもの話
子にその関数を渡すと親が再レンダリングされるたびに子も無駄に再レンダリングされる
tsconst Parent = (props) => { // このpropsが変わるたびにParentは再レンダリングされる(普通に)
const f = () => {} // そのたびにこの関数は新しく作られる
return (
<Child onClick={f} /> // fが新しくなるので無駄にChildが再レンダリングされる(React.memoを使っていても)
)
}
これを防ぐためにuseCallbackを使う
tsconst f = useCallback(() => {}, [なんか])
class時代の関数をインラインで書くな問題がFCではもっと顕著に起こる
ない
>React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list. ref
depsにdispatchを入れる意味はあるか?
objectなので、毎回生成されるので、無意味になる
JSON.stringifyする?
ロジックに依っては、 xs.length
でも良いかも
ミスったらめちゃくちゃわかりづらいバグになりそうだけど
useCallbackに第3引数を設け、自作のcompare関数を書いて比較する
こんなhooksを書いたとき
tsconst usePageNavigation = <T>() => {
const [stacks, setStacks] = useState<T[]>([]);
// ページ遷移時は、先頭に追加する
const push = useCallback((stack: T) => {
setStacks(s => [stack, ...s]);
}, []);
const pop = () => {
setStacks(([, ...rest]) => rest);
return stacks[1];
} // useCallback使う?使うならdepsはなに?
const reset = useCallback(() => {
setStacks([]);
}, []);
return {
push,
pop,
reset
};
};
pop
のdepsに入れるべき値はなにか?
stacks
?
useStateで作られたstateって変化がない場合って参照は同じものなのか?
同じものなのであれば、 stacks
でいいし、同じものでないなら stacks
と書いても無意味
そのstateが全く変わってなかったら参照は同じ
でも今回のケースではmethodを呼ぶと絶対にstateが変わるようなhooksなのでやっぱ意味ないな
stacks[0]
?
いや、意味ないなたぶん
useCallbackを使う意味がない気がする
引数を取っていない以上、 stacks
が変わるたびに再生成しないと動かなくなる
で、stacksは毎回変わるので、意味ない
本当にここをどうにかしたいなら、引数に取るべし
でも、それはinterface的に微妙なので却下
配列の中の一要素を見るとか
[arr[0].hoge]
適当に選択するのではなく、viewの更新にふさわしいkeyを指定する
頻繁に更新するべきか、そうでないか、などを鑑みながら
asyncを入れることある?
副作用?