[React] useMemo, useCallback



useMemo

useMemoの計算値を持つHookを使用してパフォーマンスを最適化する方法
import React, { useState, useRef, useMemo } from "react";
import CreateUser from "./CreateUser";
import UserList from "./UserList";

// useMemo: 특정값이 바뀌었을 때만 특정 함수를 실행해서 연산하도록 처리

function countActiveUsers(users) {
  console.log("활성 사용자 수 세는 중");
  return users.filter((user) => user.active).length;
  // active가 true인 사용자 필터링해 수를 연산해서 가져옴
}

function App() {
  const [inputs, setInputs] = useState({
    username: "",
    email: "",
  });

  const { username, email } = inputs; // 미리 추출
  const onChange = (e) => {
    const { name, value } = e.target;
    setInputs({
      ...inputs, 
      [name]: value,
    });
  };

  const [users, setUsers] = useState([
    {
      id: 1,
      username: "su",
      email: "[email protected]",
      active: true,
    },
    {
      id: 2,
      username: "liz",
      email: "[email protected]",
      active: false,
    },
    {
      id: 3,
      username: "ro",
      email: "[email protected]",
      active: false,
    },
  ]);

  const nextId = useRef(4); 

  const onCreate = () => {
    const user = { 
      id: nextId.current,
      username,
      email,
    };
    setUsers(users.concat(user));
    setInputs({
      username: "",
      email: "",
    });

    nextId.current += 1;
  };

  const onRemove = (id) => {
    setUsers(users.filter((user) => user.id !== id));
  };

  const onToggle = (id) => {
    setUsers(
      users.map((user) =>
        user.id === id ? { ...user, active: !user.active } : user
      )
    );
  };

  const count = useMemo(() => countActiveUsers(users), [users]);
  // 이 함수는 users가 바뀔 때에만 호출되고, 그렇지 않으면 이전에 만든 값을 재호출한다.
  return (
    <>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} onRemove={onRemove} onToggle={onToggle} />
      <div>활성 사용자 수 : {count} </div>
    </>
  );
}

export default App;

// filter를 사용해서 특정 조건이 만족할 때만 추출

useMemo:一部の値が変更された場合にのみ、特定の関数が実行されます.
const count = useMemo(() => countActiveUsers(users), [users]);
最初のパラメータを使用して演算する関数を定義します.
2番目のパラメータはdeps配列を加えます.
この配列の内容が変更された場合は、登録された関数を呼び出して値を制限し、内容が変更されていない場合は、以前に計算された値を再使用します.

useCallback

Hook関数は、以前に作成した関数を再作成せずに再使用する方法です.useMemoと同様に、関数のために設計されたHookである.
propsが変更されていない場合は、以前に作成した結果を再利用できるように、関数を再利用する必要があります.
import React, { useState, useRef, useMemo, useCallback } from "react";
import CreateUser from "./CreateUser";
import UserList from "./UserList";

function countActiveUsers(users) {
 console.log("활성 사용자 수 세는 중");
 return users.filter((user) => user.active).length;
}

function App() {
 const [inputs, setInputs] = useState({
   username: "",
   email: "",
 });

 const { username, email } = inputs; 
 const onChange = useCallback(
   (e) => {
     const { name, value } = e.target;
     setInputs({
       ...inputs, 
       [name]: value,
     });
   },
   [inputs]
 );
 // 의존하고 있는 상태 inputs를 넣어줌, inputs가 바뀔 때만 새로 만들어짐
 const [users, setUsers] = useState([
   {
     id: 1,
     username: "su",
     email: "[email protected]",
     active: true,
   },
   {
     id: 2,
     username: "liz",
     email: "[email protected]",
     active: false,
   },
   {
     id: 3,
     username: "ro",
     email: "[email protected]",
     active: false,
   },
 ]);

 const nextId = useRef(4); 

 const onCreate = useCallback(() => {
   const user = {
     id: nextId.current,
     username,
     email,
   };
   setUsers(users.concat(user));
   setInputs({
     username: "",
     email: "",
   });

   nextId.current += 1;
 }, [username, email, users]);

 const onRemove = useCallback(
   (id) => {
     setUsers(users.filter((user) => user.id !== id));
   },
   [users]
 );

 const onToggle = useCallback(
   (id) => {
     setUsers(
       users.map((user) =>
         user.id === id ? { ...user, active: !user.active } : user
       )
     );
   },
   [users]
 );

 const count = useMemo(() => countActiveUsers(users), [users]);
 return (
   <>
     <CreateUser
       username={username}
       email={email}
       onChange={onChange}
       onCreate={onCreate}
     />
     <UserList users={users} onRemove={onRemove} onToggle={onToggle} />
     <div>활성 사용자 수 : {count} </div>
   </>
 );
}

export default App;