React usememo & usecallback

최정환·2022년 1월 1일
0

React

목록 보기
4/7

useMemo

React는 컴퍼넌트를 렌더링한 뒤 이전 렌더링된 결과와 비교하여 DOM업데이트를 결정한다.
만약 렌더링의 결과가 이전과 다르다면 React는 DOM을 업데이트 할것이다.

React.memo는 렌더링 결과를 메모이징(memoizing)함으로 불필요한 렌더링을 줄여준다.

component의 props가 변경되지 않았다면 rerendering하지 않도록 방지해준다.

🔧

function Book({title, writer}){
return(
<div>
<div>title : {title}</div>
<div>writer : {writer}</div>
</div>
)
}

export default React.memo(Book);

React.memo(Book)는 새로 메모이징된 컴퍼넌트인 MemoizedBook을 반환한다.
만약 title, writer과 같은 props의 변경이 없다면 다음 렌더링 때 메모이징된 내용을 그대로 사용하게된다.


props 동등 비교 커스터마이징

React.memo는 props혹은 props의 객체를 비교할 때 얕은 비교를 한다.
비교방식을 수정하기 위해선 아래와 같이 만들어주면 된다.

React.memo(Component,[areEqual(prevProps, nextProps)]);

ereEqual(prevProps, nextProps)함수는 두 인자(이전 props, 현재 props)가 같다면 true를 반환할 것이다.



🤔 React.memo를 사용해야할 때

  1. 같은 props로 렌더링이 자주 일어나는 컴퍼넌트
    React.memo는 함수형 component에 적용되어 같은 props에 같은 렌더링 결과를 제공한다.

React.memo를 사용하기 가장 좋은 케이스는 함수형 component가 같은 props로 자주 렌더링 될거라 예상될때.


🔧 react-beautiful-dnd를 사용해서 toDo의 index하나를 옮기는데 toDo의 배열 전체가 rerendering되는 상황이다.

import { Draggable } from "react-beautiful-dnd";
import styled from "styled-components";
import React from "react";

const Card = styled.div`
  border-radius: 5px;
  padding: 5px 10px;
  margin-bottom: 5px;
  background-color: ${(props) => props.theme.cardColor};
`;

interface IDragabbleCrad {
  toDo: string;
  index: number;
}

function DragabbleCard({ toDo, index }: IDragabbleCrad) {
  return (
    <Draggable key={toDo} draggableId={toDo} index={index}>
      {(magic) => (
        <Card
          ref={magic.innerRef}
          {...magic.draggableProps}
          {...magic.dragHandleProps}
        >
          {toDo}
        </Card>
      )}
    </Draggable>
  );
}

export default React.memo(DragabbleCard);

DragabbleCard가 변화하는 상황일때만 rendering하기 위해서 memo를 사용한다.
이외에 API를 받아오는 등 많은 자원을 불필요한 redering을 하기 위해 낭비하는 상황에서 사용한다.



❌ React.memo을 사용하지 말아야할 때

쓸모없는 props 비교

rendering이 될때 props가 다른 경우가 대부분인 component를 생각해보면 메모이제이션의 이점을 얻기 힘들다.

props가 자주 변하는 component를 React.memo()로 래핑하는 것은 좋은 방법이 아니다.



결론

React.memo은 성능 개선 도구이다. React.memo을 통해 component의 rerendering을 피할 수 있지만 메모이제이션에 의존해선 안된다.



useCallback

메모제이션된 콜백을 반환한다.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useCallback(fn, deps)은 useMemo(() => fn, deps)와 같다.

함수를 불필요한 렌더링을 줄이고 재활용 가능하기 때문에 콜백을 전달할 때 유용하다.

ex) onClick

function Btn(){
	const clickFn = useCallback(console.log("ds"));
  return <div onClick={clickFn}>버튼</div>
}

우리가 일반적으로 사용하는 이벤트에 콜백으로 ()=> fn를 주는 방식은 컴포넌트가 렌더링이 될때마다 함수를 다시 정의하기 때문에 불필요한 렌더링이 생기는 경우다.

useCallback을 이용해서 함수를 메모제이션 한다면 불필요한 함수 재정의를 막을 수 있다.

하지만 이렇게 작은 부분은 성능에 영향을 주는 경우가 없기 때문에 이런 경우는 사용하지 않아도 괜찮다.

0개의 댓글