サイトアイコン 上尾市のWEBプログラマーによるブログ

「Reactハンズオンラーニング」の感想・備忘録3

「Reactハンズオンラーニング」の感想・備忘録2の続き

フック

7.1.1 依存配列

import {useEffect, useState} from 'react'

function usePosts() {
  const [posts, setPosts] = useState([]);
  useEffect(() => {
    // 記事のサブスクライブなど
    setPosts(["記事1", "記事2"])
  }, [])
  return posts;
}

export default usePosts

利用時

import usePosts from './effect-hooks'
function Effect() {
  const posts = usePosts()
  return (
    <div style={{border: "1px solid #ccc", padding: "50px"}}>
      <h2>Effect.js</h2>
      {posts.map(post=><p>{post}</p>)}
    </div>
  );
}

export default Effect;

7.1.2 依存配列の同一性チェック

 import {useEffect, useState} from 'react'
 
 function Effect2() {
   const [, setText] = useState("");
   const words = ["aaa", "bbb"]
   useEffect(() => {
     window.addEventListener("keydown", setText)
     console.log("Effect2 useEffect called");
   }, [words])
   return (
     <div style={{border: "1px solid #ccc", padding: "50px"}}>
     <h2>Effect2.js</h2>
     </div>
   );
 }
 
 export default Effect2;

以下のように、配列やオブジェクトを関数の外で初期化すると再描画時は不変となる。

 import {useEffect, useState} from 'react'
 
 const words = ["aaa", "bbb"]
 function Effect2() {
   const [, setText] = useState("");
   useEffect(() => {
     window.addEventListener("keydown", setText)
     console.log("Effect2 useEffect called");
   }, [words])
   return (
     <div style={{border: "1px solid #ccc", padding: "50px"}}>
     <h2>Effect2.js</h2>
     </div>
   );
 }
 
 export default Effect2;

useMemo

import {useEffect, useState} from 'react'

function Effect3({str}) {
  const words = str.split(" ")
  const [, setText] = useState("");
  useEffect(() => {
    window.addEventListener("keydown", setText)
    console.log("Effect3 useEffect called");
  }, [words])
  return (
    <div style={{border: "1px solid #ccc", padding: "50px"}}>
      <h2>Effect3.js</h2>
    </div>
  );
}

export default Effect3;

このような場合はuseMemoフックを使う。 useMemoはメモ化された値を返す。

import {useEffect, useState, useMemo} from 'react'

function Effect3({str}) {
  const words = useMemo(() => str.split(" "), [str])
  const [, setText] = useState("");
  useEffect(() => {
    window.addEventListener("keydown", setText)
    console.log("Effect3 useEffect called");
  }, [words])
  return (
    <div style={{border: "1px solid #ccc", padding: "50px"}}>
      <h2>Effect3.js</h2>
    </div>
  );
}

export default Effect3;

useCallback

import {useEffect, useState} from 'react'

function Effect4() {
  const [, setText] = useState("");
  const fn = ()=> {
    console.log("fn")
  }
  useEffect(() => {
    window.addEventListener("keydown", setText)
    console.log("Effect4 useEffect called");
    fn()
  }, [fn])
  return (
    <div style={{border: "1px solid #ccc", padding: "50px"}}>
      <h2>Effect4.js</h2>
    </div>
  );
}

export default Effect4;

useCallbackを使うと関数定義がキャッシュされるため、再描画しても関数fnは再生成されない。

import {useEffect, useState, useCallback} from 'react'

function Effect4() {
  const [, setText] = useState("");
  const fn = useCallback(()=> {
    console.log("fn")
  },[])
  useEffect(() => {
    window.addEventListener("keydown", setText)
    console.log("Effect4 useEffect called");
    fn()
  }, [fn])
  return (
    <div style={{border: "1px solid #ccc", padding: "50px"}}>
      <h2>Effect4.js</h2>
    </div>
  );
}

export default Effect4;
モバイルバージョンを終了