useCallback으로 함수 재사용

Doum Kim·2020년 5월 14일
0

React - 기초

목록 보기
14/20
post-thumbnail

useCallback은 특정 함수를 재사용한다.

함수형 컴포넌트는 state가 바뀔 때 마다 코드 전체가 재실행된다. 따라서 함수가 다시 만들어지고 그 함수를 props로 받는 자식
컴포넌트들이 불필요한 렌더링이 발생하게된다.

따라서 불필요한 렌더링 방지를 위해 useCallback을 사용하고 deps에 넣어 준 값이 변경되었을 때만 새로 함수를 생성한다.

아래의 App.js의 코드를 보면 onInputChange, onCreate, onRemove, onToggle 함수가 props로 자식 컴포넌트에 내려진다.
따라서 불필요한 렌더링을 막기위해 useCallback을 사용해보자.

Appp.js useCallback 사용 전

import React, { useState, useRef, useMemo } from "react";
import UserList from "./UserList";
import CreateUser from "./CreateUser";

const countActiveUser = users => {
  console.log("카운트");
  return users.filter(user => user.active).length;
};

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

  const [users, setUsers] = useState([
    {
      id: 1,
      username: "Kim",
      age: 20
    },
    {
      id: 2,
      username: "Lee",
      age: "30"
    },
    {
      id: 3,
      username: "Choi",
      age: "40"
    }
  ]);

  const nextId = useRef(4);

  const onInputChange = e => {
    const { value, name } = e.target;
    setInputs({
      ...inputs,
      [name]: value
    });
  };

  const onCreate = () => {
    const user = {
      username,
      age,
      id: nextId.current,
      active: false
    };
    setUsers([...users, user]);
    setInputs({
      username: "",
      age: ""
    });
    nextId.current += 1;
  };

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

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

  const count = useMemo(() => countActiveUser(users), [users]);

  return (
    <div>
      <CreateUser
        username={username}
        age={age}
        onChange={onInputChange}
        onCreate={onCreate}
      />
      <div>activeUser : {count}</div>
      <UserList users={users} onRemove={onRemove} onToggle={onToggle} />
    </div>
  );
}

App.js useCallback 사용 후

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

const countActiveUser = users => {
  console.log("카운트");
  return users.filter(user => user.active).length;
};

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

  const [users, setUsers] = useState([
    {
      id: 1,
      username: "Kim",
      age: 20
    },
    {
      id: 2,
      username: "Lee",
      age: "30"
    },
    {
      id: 3,
      username: "Choi",
      age: "40"
    }
  ]);

  const nextId = useRef(4);

  const onInputChange = useCallback(
    e => {
      const { value, name } = e.target;
      setInputs({
        ...inputs,
        [name]: value
      });
    },
    [inputs]
  );

  const onCreate = useCallback(() => {
    const user = {
      username,
      age,
      id: nextId.current,
      active: false
    };
    setUsers([...users, user]);
    setInputs({
      username: "",
      age: ""
    });
    nextId.current += 1;
  }, [users, username, age]);

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

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

  const count = useMemo(() => countActiveUser(users), [users]);

  return (
    <div>
      <CreateUser
        username={username}
        age={age}
        onChange={onInputChange}
        onCreate={onCreate}
      />
      <div>activeUser : {count}</div>
      <UserList users={users} onRemove={onRemove} onToggle={onToggle} />
    </div>
  );
}

0개의 댓글