🤹🏻♀️Reactの状態を理解して適切にHooksを利用する2024/02/02に公開2024/07/175件JavaScriptReactTypeScripttechGitHubで編集を提案DiscussionHoney322024/02/02に更新細かいところで失礼します filteredTodo については、 const [filter, setFilter] = useState<"marked" | "unmarked" | "all">("all"); const filteredMemo = ( filter === "marked" ? memos.filter((memo) => memo.marked) : filter === "unmarked" ? memos.filter((memo) => !memo.marked) : memos ); と生の式 + 三項演算子を使って書くほうが良いと思います。 もしくは、計算結果がキャッシュされることを除いて同じ意味になりますが、useMemo を使うことが多いです。(useMemo の中はアロー関数が書けるため、三項演算子を使わなくて済むので) const [filter, setFilter] = useState<"marked" | "unmarked" | "all">("all"); const filteredMemo = useMemo(() => { if (filter === "marked") return memos.filter((memo) => memo.marked); if (filter === "unmarked") return memos.filter((memo) => !memo.marked); return memos; }, [filter, memo]); filterMemos(filter) のような形でも正しく動きはしますが、上記のように生の三項演算子を使った式 or useMemo で書くことで、「filteredMemo は、filter, memo から計算できる状態である」 (この言い回しは react.dev/learn にも度々登場します)と意識することが出来て意図の共有がしやすいと思います。 返信を追加saku2024/02/02に更新コメントありがとうございます! 1番目の改善提案に関しては、私の書き方をこの場合三項演算子で書いた方が良いというものですね! 2番目の改善提案にある、useMemoを使用する意図がとても勉強になります!🙌🏻 確かにフックの依存配列は発火タイミングを明示してあげることができるという働きもありました。 加筆しておきます! Honey322024/02/02少しでも学習のお役に立てたなら幸いです! (コードのタイポ、意図の不明確な文章を少し修正しました) 返信を追加クロパンダ2024/02/03に更新メチャクチャよくまとまってますね…! 読んでる途中ですが、「useCallback 重たい関数をキャッシュするためのフック」の部分は誤りと思います。重たい関数というものがそもそもなく、レンダーごとに関数が再生成される→関数は参照が等しくないと等価とみなされないのが問題であり、「重いかどうか」は関係ないので (後ろの「レンダー前後でuseCallback依存配列の値に差異がない場合に関数の再生成をスキップしてくれるフックです。」の説明は合ってるので、重い関数云々のとこピンポイントでのミスだと思います) 返信を追加saku2024/02/04読んでいただきありがとうございます🌟 確かに、実行コスト(「重さ」)ゆえuseCallbackを使っているのではないですね...! Profilerなどで測定した結果、著しくパフォーマンスに影響を与えているコンポーネントが関数propsを受けていた場合に、その関数定義をuseCallbackでキャッシュ&コンポーネントをmemo化してあげることでパフォーマンス改善の第一歩を踏み出せるという理解でした。 「重たいコンポーネントをキャッシュしたいときに併用が考えられるフック」というイメージですが、単に「関数をキャッシュするためのフック」と修正しておきます! 返信を追加
Honey322024/02/02に更新細かいところで失礼します filteredTodo については、 const [filter, setFilter] = useState<"marked" | "unmarked" | "all">("all"); const filteredMemo = ( filter === "marked" ? memos.filter((memo) => memo.marked) : filter === "unmarked" ? memos.filter((memo) => !memo.marked) : memos ); と生の式 + 三項演算子を使って書くほうが良いと思います。 もしくは、計算結果がキャッシュされることを除いて同じ意味になりますが、useMemo を使うことが多いです。(useMemo の中はアロー関数が書けるため、三項演算子を使わなくて済むので) const [filter, setFilter] = useState<"marked" | "unmarked" | "all">("all"); const filteredMemo = useMemo(() => { if (filter === "marked") return memos.filter((memo) => memo.marked); if (filter === "unmarked") return memos.filter((memo) => !memo.marked); return memos; }, [filter, memo]); filterMemos(filter) のような形でも正しく動きはしますが、上記のように生の三項演算子を使った式 or useMemo で書くことで、「filteredMemo は、filter, memo から計算できる状態である」 (この言い回しは react.dev/learn にも度々登場します)と意識することが出来て意図の共有がしやすいと思います。 返信を追加
saku2024/02/02に更新コメントありがとうございます! 1番目の改善提案に関しては、私の書き方をこの場合三項演算子で書いた方が良いというものですね! 2番目の改善提案にある、useMemoを使用する意図がとても勉強になります!🙌🏻 確かにフックの依存配列は発火タイミングを明示してあげることができるという働きもありました。 加筆しておきます! Honey322024/02/02少しでも学習のお役に立てたなら幸いです! (コードのタイポ、意図の不明確な文章を少し修正しました) 返信を追加
クロパンダ2024/02/03に更新メチャクチャよくまとまってますね…! 読んでる途中ですが、「useCallback 重たい関数をキャッシュするためのフック」の部分は誤りと思います。重たい関数というものがそもそもなく、レンダーごとに関数が再生成される→関数は参照が等しくないと等価とみなされないのが問題であり、「重いかどうか」は関係ないので (後ろの「レンダー前後でuseCallback依存配列の値に差異がない場合に関数の再生成をスキップしてくれるフックです。」の説明は合ってるので、重い関数云々のとこピンポイントでのミスだと思います) 返信を追加
saku2024/02/04読んでいただきありがとうございます🌟 確かに、実行コスト(「重さ」)ゆえuseCallbackを使っているのではないですね...! Profilerなどで測定した結果、著しくパフォーマンスに影響を与えているコンポーネントが関数propsを受けていた場合に、その関数定義をuseCallbackでキャッシュ&コンポーネントをmemo化してあげることでパフォーマンス改善の第一歩を踏み出せるという理解でした。 「重たいコンポーネントをキャッシュしたいときに併用が考えられるフック」というイメージですが、単に「関数をキャッシュするためのフック」と修正しておきます! 返信を追加
Discussion
細かいところで失礼します
filteredTodo については、
と生の式 + 三項演算子を使って書くほうが良いと思います。
もしくは、計算結果がキャッシュされることを除いて同じ意味になりますが、useMemo を使うことが多いです。(useMemo の中はアロー関数が書けるため、三項演算子を使わなくて済むので)
filterMemos(filter)のような形でも正しく動きはしますが、上記のように生の三項演算子を使った式 or useMemo で書くことで、「filteredMemo は、filter, memo から計算できる状態である」 (この言い回しは react.dev/learn にも度々登場します)と意識することが出来て意図の共有がしやすいと思います。コメントありがとうございます!
1番目の改善提案に関しては、私の書き方をこの場合三項演算子で書いた方が良いというものですね!
2番目の改善提案にある、
useMemoを使用する意図がとても勉強になります!🙌🏻確かにフックの依存配列は発火タイミングを明示してあげることができるという働きもありました。
加筆しておきます!
少しでも学習のお役に立てたなら幸いです!
(コードのタイポ、意図の不明確な文章を少し修正しました)
メチャクチャよくまとまってますね…!
読んでる途中ですが、「useCallback 重たい関数をキャッシュするためのフック」の部分は誤りと思います。重たい関数というものがそもそもなく、レンダーごとに関数が再生成される→関数は参照が等しくないと等価とみなされないのが問題であり、「重いかどうか」は関係ないので
(後ろの「レンダー前後でuseCallback依存配列の値に差異がない場合に関数の再生成をスキップしてくれるフックです。」の説明は合ってるので、重い関数云々のとこピンポイントでのミスだと思います)
読んでいただきありがとうございます🌟
確かに、実行コスト(「重さ」)ゆえ
useCallbackを使っているのではないですね...!Profilerなどで測定した結果、著しくパフォーマンスに影響を与えているコンポーネントが関数propsを受けていた場合に、その関数定義を
useCallbackでキャッシュ&コンポーネントをmemo化してあげることでパフォーマンス改善の第一歩を踏み出せるという理解でした。「重たいコンポーネントをキャッシュしたいときに併用が考えられるフック」というイメージですが、単に「関数をキャッシュするためのフック」と修正しておきます!