본문 바로가기
프론트엔드/React

useCallback, React.memo

by alswlfl 2022. 11. 24.

useCallback

함수를 memoization하기 위해 사용되는 hook함수 → useMemo와 비슷한 Hook

💡 useMemo특정 결과값을 재사용 할 때 사용
     useCallback특정 함수를 새로 만들지 않고 재사용하고 싶을 때 사용
  • 컴포넌트에서 props가 바뀌지 않으면 Virtual DOM에 새로 렌더링하는 것도 하지 않고, 컴포넌트의 결과물을 재사용하는 최적화 작업 → 함수 재사용

기본 구조

const memoizedCallback = useCallback(함수, 배열);

첫 번째 파라미터: 인자로 넘어온 함수

두 번째 파라미터: 넘어온 배열 내의 값이 변경될 때까지 저장해놓고 재사용할 수 있게 해줌

 

  • 해당 컴포넌트가 렌더링되어도 그 함수가 의존하는 값들이 바뀌지 않는 한 기존 함수 계속 반환
const add = () => x+y; 
const add = useCallback(() => x+y, [x,y]);
// x 또는 y 값이 바뀌면 새로운 함수가 생성되어 add변수에 할당되고, x와 y값이 동일하다면
// 다음 렌더링 때 함수 재사용
import React, { useRef, useState, useMemo, useCallback } from "react";

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

const onCreate = useCallback(() => {
    const user = {
      id: nextId.current,
      username,
      email,
    };
    setUsers(users.concat(user));
    setInputs({
      username: "",
      email: "",
    });
    nextId.current += 1; //값 수정 시, .current 값 수정하면 되고, 조회할 때도 .current조회하면 됨
  }, [users, username, email]);

const onRemove = useCallback(
    (id) => {
      //user.id가 파라미터로 일치하지 않는 원소만 추출하여 새로운 배열을 만듦
      //=user.id가 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]
  );

❗️ 함수 안에서 사용하는 상태 혹은 props가 있다면 deps 배열 안에 포함시켜야 함

→ 만약 deps 배열 안에 해당 값을 넣지 않으면, 함수 내에서 해당 값들을 참조할 때 가장 최신 값을 참조한다고 보장 못함

❗️ props로 받아온 함수 있으면, 이 함수도 deps에 넣어야 함

 

useCallback은 useMemo 기반으로 만들어짐

const onToggle = useMemo(
	() => () => {
		/* ... */
	},
	[users]
);

→ useCallback을 사용하였을 때, 눈에 띄는 최적화는 없음 → 컴포넌트 렌더링 최적화 작업해주어야 성능이 최적화 됨(React DevTools: 어떤 컴포넌트가 렌더링되고 있는지 확인하기 위한 프로그램)

 


React.memo를 사용한 컴포넌트 리렌더링 방지

컴포넌트의 props가 바뀌지 않았을 때, 리렌더링 방지하여 컴포넌트의 리렌더링 성능 최적화 해주는 함수컴포넌트에서 리렌더링이 필요한 상황에서만 리렌더링 하도록 설정

 

사용법

export default React.memo(UserList); //컴포넌트 이름을 React.memo로 감싸주면 됨

 

React.memo에서 두 번째 파라미터에 propsAreEqual 이라는 함수를 사용하여 특정 값들만 비교 가능 → 잘못 사용하면 의도치 않은 버그 발생하기 쉬움

export default React.memo(
	UserList,
	(prevProps, nextProps) => prevProps.users === nextProps.users
);

 

주의할 점

useMemo, useCallback, React.memo는 컴포넌트 성능을 실제로 개선할 수 있는 상황에서만 사용하길 권장

ex) 렌더링 최적화 하지 않을 컴포넌트에 React.memo를 사용하는것은 불필요한 props 비교하는 것임

'프론트엔드 > React' 카테고리의 다른 글

커스텀 Hooks 만들기  (0) 2022.11.24
useReducer  (0) 2022.11.24
useEffect와 useMemo  (0) 2022.11.23
컴포넌트 렌더링  (0) 2022.11.23
✅ 배열 내장 함수(자바스크립트)  (0) 2022.11.17