memo
자식 컴포넌트의 재렌더링 막으려면 memo
버튼을 누르면 count가 +1씩 되는 버튼을 생성하자.
🕹️Cart.js
import { useState } from 'react';
function Child(){
return <div>자식임</div>
}
function Cart(){
const [count, setCount] = useState(0);
return(
<div>
<Child></Child>
<button onClick={() => setCount(count+1)}>+</button>
</div>)
}
이제 버튼을 누를 때마다 Cart 컴포넌트가 재렌더링이 된다. Cart 컴포넌트가 재렌더링되므로 <Child>와 같은 자식 컴포넌트들도 전부 재렌더링이 된다. 재런데링되는지 콘솔로 확인해보자.
function Child(){
console.log('재렌더링됨')
return <div>자식임</div>
}
버튼을 누를 때마다 콘솔이 찍힌다.
리액트는 원래 이런식으로 동작한다. 하지만 이런 것들이 나중에는 성능저하가 된다. 만약 <Child>가 렌더링 시간이 오래 걸리는 친구라면 button을 누를 때마다 <Child>라는 무거운 친구도 재렌더링되니까 시간이 오래걸릴 수 있다.
그래서 <Child> 컴포넌트를 꼭 필요할 때만 재렌더링되도록 해야 한다. 이때 쓰는게 memo다.
함수형 컴포넌트로 컴포넌트를 생성해주고, 함수를 memo로 감싼다.
import { useState, memo } from 'react';
const Child = memo(function(){
console.log('재렌더링됨')
return <div>자식임</div>
})
그러면 <Child>는 꼭 필요할 때만 재렌더링되기 때문에 버튼을 눌러도 콘솔이 찍히지 않는다.
⭐memo로 재렌더링 오래 걸리는 컴포넌트를 감싸놓으면 좋다.
memo 동작 원리: props가 변할 때만 재렌더링해줌
memo는 그냥 재렌더링을 막아주는게 아니라, **props가 변할 때만 재렌더링을 해준다**. <Child>에 props인 count를 줘서 확인해보자.
import { useState, memo } from 'react';
const Child = memo(function(){
console.log('재렌더링됨')
return <div>자식임</div>
})
function Cart(){
const [count, setCount] = useState(0);
return(
<div>
<Child count={count}></Child>
<button onClick={() => setCount(count+1)}>+</button>
</div>)
}
그러면 버튼을 누를 때마다 <Child>에 props값이 변하므로 <Child>도 재렌더링된다.
props가 길고 복잡하면 손해일 수도
이걸 통해서 memo를 다 감싸면 안좋다는 걸 알게된다. 왜냐하면 memo로 감싼 컴포넌트는 재렌더링하기 전에
기존props === 신규props
를 계속 비교하고, 재렌더링 여부를 결정한다.
그래서 만약 <Child>로 전송되는 props가 길고 복잡하다면 기존 props와 신규 props를 비교하는데도 오랜 시간이 걸리기 때문에 손해다.
그러니까 온갖 컴포넌트에 다 memo를 갖다 붙이지 말고, 진짜 꼭 필요한 무거운 컴포넌트에만 붙이자. 근데 대부분에는 붙일 필요가 없는데 그냥 참고로만 알아두자.
useMemo
컴포넌트 렌더링시 1회만 실행해줌
무거운 연산을 하는 함수가 하나 있다고 하자.
function 함수(){
return 반복문10억번 돌린 결과
}
function Cart(){
const result = 함수();
}
Cart에 그냥 result = 함수()로 써놓으면 단점이 있다. Cart가 재렌더링될 때마다 이 함수가 계속 실행되기 때문에 매우 비효율적이기 때문이다.
개선을 하고 싶다면 useMemo를 이용해서 작성하자. 작성하는 방법은 useEffect와 매우 유사하다.
import { useMemo } from 'react';
function 함수(){
return 반복문10억번 돌린 결과
}
function Cart(){
const result = useMemo(() => 함수())
}
함수를 return해주는데, 그러면 Cart 컴포넌트가 처음 렌더링될 때에만 실행이 되고, 그 이후로는 영영 실행이 되지 않는다.
useEffect처럼 얘도 dependency를 집어 넣을 수 있다.
function Cart(){
const result = useMemo(() => 함수(), [state])
}
그럼 state가 변경될 때에만 함수()가 실행돼서 result에 넣어진다.
그래서 꼭 필요할 때에만 함수를 실행시키고 싶으면 useMemo나 useEffect를 갖다 쓰면 된다.
useMemo vs useEffect
실행 시점에 차이가 있다.
useEffect는 html 보여주는 실행이 모두 끝나면 실행이 되고,
useMemo는 렌더링 될 때 같이 실행이 된다.
'Front-End: Web > React.js' 카테고리의 다른 글
[React] 엘리먼트 리스트에 key가 왜 필요해? (0) | 2022.12.06 |
---|---|
[코딩애플] 성능개선 3: useTransition, useDeferredValue (0) | 2022.11.09 |
[코딩애플] 성능개선 1: 개발자 도구 & lazy import (0) | 2022.11.08 |
[코딩애플] react-query 사용하여 실시간 데이터 가져오기 (0) | 2022.11.08 |
[코딩애플] Redux 사용해서 쉽게 state 관리하기! (0) | 2022.11.03 |