이다닷

[React] Day 20 - useCallback를 사용하여 함수 재사용하기 본문

React

[React] Day 20 - useCallback를 사용하여 함수 재사용하기

이다닷 2023. 9. 24. 18:00

📌useCallback

  useCallback는 useMemo와 비슷한 Hook 함수이다. useMemo는 특정 결과값을 재사용하는 반면, useCallback는 특정 함수를 재사용 할 수 있게 해준다.

 

📢사실 지금까지 사용되던 onCreate, onRemove, onToggle 함수들은 컴포넌트가 리렌더링 될 때마다 새로 만들어지고 있다. 사실 함수를 새로 만드는 것이 리소스를 많이 차지하는 일은 아니지만 한번 만든 함수를 재사용하는 것은 여전히 중요하다.

   -> 그 이유는, 추후에 컴포넌트에서 props가 바뀌지 않으면 Virtual DOM에 새로 렌더링 하는 것을 하지않고, 컴포넌트의 결과물을 재사용하는 최적화 작업을 할때, 함수를 재사용 해야하기 때문이다. 

 

📢useCallBack를 사용할 때에는 함수 안에서 사용하는 상태 혹은 props가 있다면 첫 번째 파라미터에는 함수, 두 번째 파라미터에는 의존값이 들어있는 배열(deps) 안에 함수에서 사용하는 값을 넣어주여야 한다. 

  -> 그 이유는, 나중에 함수에서 값을 참조 할 때 가장 최신 값을 참조 할 것이라고 보장 할 수 없다. props로 받아온 함수가 있다면, 이 또한 deps에 넣어주어야 한다. 

 

APP.js 변경 (useCallback 함수 사용)

import React, { useRef, useState, useMemo, useCallback } from 'react';
import UserList from './qoffhvjxm/UserList';
import CreateUser from './qoffhvjxm/CreateUser';

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

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

  // useCallback 함수 사용하기
  const onChange = useCallback(
    e => {
      const { name, value } = e.target;
      setInputs({
        ...inputs,
        [name]: value
      }, [inputs]
      );
    });
  //

  const [users, setUsers] = useState([
    {
      id: 1,
      username: 'dndhk',
      email: 'dndhk@gmail.com',
      active: true
    }, {
      id: 2,
      username: 'Lee',
      email: 'Lee@gmail.com',
      active: true
    }, {
      id: 3,
      username: 'dada',
      email: 'dada@gmail.com',
      active: true
    }
  ]);

  const nextId = useRef(4);

  // useCallback 함수 사용하기
  const onCreate = useCallback(
    () => {
      const user = {
        id: nextId.current,
        username,
        email
      };
      setUsers([...users, user]);
      setInputs({
        username: '',
        email: ''
      });
      nextId.current += 1;
    }, [users, username, email]
  );
  //

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

  // useCallback 함수 사용하기
  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}
      ></CreateUser>
      <UserList users={users} onRemove={onRemove} onToggle={onToggle}></UserList>
      <div>활성사용자 수 : {count}</div>
    </>
  );
}

export default App;