本日はReactフックの『useCollback』について理解を深めてもらいたく初学様に向けて解説していきます。
事前として、当ブログのこの記事ではフックである『useState』と 『useEffect』の理解をしており精通している事を前提とした解説となりますのでご了承下さい。
useCallbackとは
『useCallback』フックのReactドキュメントによると、フック自体は次の通りに記述されています。
メモ化されたコールバックを返し、インラインコールバックと依存関係の配列を渡します。
useCallback依存関係の1つが変更された場合にのみ変更され、メモ化されたバージョンのコールバックを返します。
以上がドキュメントによる解説です。
これは、不要なレンダリングを防ぐために参照の同等に依存する最適化された、子のコンポーネントにコールバックを渡すときに役立ちます。
つまり『不要な再レンダリングを防ぐ方法をあなたに提供致します』と言う事になります。
それでは今回は、以前当ブログでご紹介したuseEffectフックによるfetchでAPIを取得し表示する方法を紹介しましたが、その記事をそのまま使用し
コンポーネントの状態に割り当てuseCallbackフックで書き直してみましょう。
useEffectフックに精通されてない方はこちらで学んで下さい。
まずは以前のコードの確認をお願いします。
useEffctによるFetch
これは、async/awaitを使用しないフェッチとなります。
// useEffect fetch API import { useEffect, useState } from 'react'; const App = () => { const [posts, setPosts] = useState([]) useEffect(() => { fetch('https://jsonplaceholder.typicode.com/posts') .then(res => res.json()) .then(data => {setPosts(data) }) },[]) const usePosts = posts.map((post)=>{ return <div> <li>{post.id}</li> <li>{post.title}</li> </div> }) return ( <div> <ul> {usePosts} </ul> </div> ); } export default App;
これを、useCallbackフックで書き直します。
useCallbackで書き直し
// App.js import { useEffect, useState, useCallback } from 'react'; const App = () => { const [posts, setPosts] = useState([]) //修正点 const fetchPosts = useCallback(() => { //メモ化するコールバック関数 fetch('https://jsonplaceholder.typicode.com/posts') .then(res => res.json()) .then(data => {setPosts(data) }) },[setPosts]) //修正点 useEffect(() => { fetchPosts() },[fetchPosts]) const usePosts = posts.map((post)=>{ return <div> <li>{post.id}</li> <li>{post.title}</li> </div> }) return ( <div> <ul> {usePosts} </ul> </div> ); } export default App;
もちろんですがブラウザでの表示は変わりません。
DEMO
1 sunt aut facere repellat provident occaecati excepturi optio reprehenderit 2 qui est esse 3 ea molestias quasi exercitationem repellat qui ipsa sit aut 4 eum et est occaecati 5 nesciunt quas odio //(続く)省略
では一体何が起きているのか
例えばuseCallbackフックを使用しない場合
// useEffect fetch API const fetchPosts =() => { const [posts, setPosts] = useState([]) fetch('https://jsonplaceholder.typicode.com/posts') .then(res => res.json()) .then(data => {setPosts(data) }) } useEffect(() => { fetchPosts() },[]) } export default fetchPosts;
この場合、無数の再レンダリングを回避するために依存関係配列を含め実際には再レンダリングを防ぐために機能致しますが、Reactはエラーをスローします。
ReactHook 『useEffect』には依存関係がありません
ですがこのuseCallbackフックを使用しない場合だと『fetchPosts』がuseEffectフックに必要な依存関係であることを意味します。
それを依存関係配列に含めると、再レンダリングによりるサイクルが繰り返されていく事になります。
それを『fetchPosts』内でuseCallbackフックを呼び出し実行してあげます。
const fetchPosts = useCallback(() => { //メモ化するコールバック関数 } useEffect(() => { fetchPosts() },[fetchPosts])
こうする事でuseEffectフックがしっかりと機能するため、関数コンポーネントはマウント時に過度に再レンダリングしたりエラーをスローしたりすることはなく、データをフェッチしてくれます。
アプリケーションをより効率的にし、不必要な再レンダリングを回避できます。
useCallbackフックの欠点は、主にコードの複雑さです。
useCallbackフックを追加しても意味がなく、関数の再作成を受け入れる必要がある状況はたくさんあります。
これで前回のコードを修正した調整は以上となります。
本日は以上となります。
最後までこの記事を読んで頂きありがとうございます。