[React] useMemo, useCallback

sue·2021년 1월 18일
0

react note

목록 보기
9/17

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: "susu@gmail.com",
      active: true,
    },
    {
      id: 2,
      username: "liz",
      email: "lili@gmail.com",
      active: false,
    },
    {
      id: 3,
      username: "ro",
      email: "ro@gmail.com",
      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]);

첫번째 파라미터로 어떻게 연산할지 정의하는 함수,
두번째 파라미터로 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: "susu@gmail.com",
     active: true,
   },
   {
     id: 2,
     username: "liz",
     email: "lili@gmail.com",
     active: false,
   },
   {
     id: 3,
     username: "ro",
     email: "ro@gmail.com",
     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;

0개의 댓글