📌 memo
: 컴포넌트를 인수로 받아 최적화된 컴포넌트로 만들어 반환
- React의 내장 함수
- 얕은 복사 ('==='로 비교, 주소값 X)
- 최적화된 컴포넌트는 props를 기준으로 메모이제이션 된다.
- 메모이즈드 컴포넌트(Memoized Componenet, 최적화된 컴포넌트)는
부모 컴포넌트가 리렌더링 되더라도, 자신이 받는 props가 바뀌지 않으면 다시는 리렌더링이 실행되지 않도록 함
👉 불필요한 리렌더링 방지
✨ 고차 컴포넌트(HOC, Higher Order Component)
: 컴포넌트를 인수로 받아 해당 컴포넌트에 추가적인 기능(최적화, 메모이제이션)을 덧붙여 새로운 컴포넌트를 반환해주는 컴포넌트
📌 memo 사용하기
📍 memo 불러오기
import { memo } from "react";
📍 memo 호출하기
memo(컴포넌트[, 콜백 함수]);
- 컴포넌트: 최적화하고 싶은 컴포넌트
- 컴포넌트 외부에 memo 호출
- 콜백 함수는 생략 가능
export default memo(Header);
📌 컴포넌트 최적화하기
📍 Header.jsx는 렌더링 될 필요가 없음 👉 최적화된 컴포넌트로 바꾸기
- 인수로 받은 Header 컴포넌트를 props가 변경되지 않았을 때에는 리렌더링 하지 않도록 최적화해서 반환해줌
- 메모이즈드 컴포넌트를 반환
import { memo } from "react";
import "./Header.css";
const Header = () => {
return (
<div className="Header">
<h2>오늘은 📆</h2>
<h1>{new Date().toDateString()}</h1>
{/* // Date 객체 생성 후 String으로 변환 */}
</div>
)
}
export default memo(Header);
📍 값이 바뀌는 하나의 TodoItem만 렌더링하기
- TodoItem 컴포넌트에 전달되는 onUpdate, onDelete가 App 컴포넌트가 리렌더링 될 때마다 새롭게 생성되어 전달됨
👉 함수가 매번 새롭게 전달될 때마다 다른 주소값을 가지기 때문에 다른 값으로 인지함
👉 memo 메서드는 props가 바뀌었다고 판단
const TodoItem = ({id, isDone, content, date, onUpdate, onDelete}) => {
- memo(TodoItme)은 리렌더링이 발생할 때마다 현재의 props와 과거의 props를 비교, 두 개의 props가 같은 값인지 다른 값인지를 판단해서 TodoItem 컴포넌트를 리렌더링할 지 말 지를 결정한다.
👉 memo는 얕은 복사를 하기 때문에 객체 타입의 값은 무조건 서로 다른 값이라고 판단한다.
📌 객체 타입의 최적화 방법 2가지
방법 1.
useCallback 사용하기
: 리렌더링 되더라도 다시 생성되지 않게 방지하는 방법
방법 2.
TodoItem의 memo 함수 안에 두 번째 인수로 콜백 함수를 추가하여 커스터마이징
: 컴포넌트가 리렌더링 될 때마다 해당 컴포넌트에 과거의 props와 현재의 props를 전달하여 함수의 반환값에 따라 props가 바뀌었는지를 판단
- {id, isDone, content, date}가 변했을 때만 리렌더링 하면 됨
export default memo(TodoItem, (prevProps, nextProps)=>{
// 함수의 반환값에 따라 props가 바뀌었는지를 판단
// True -> props 바뀌지 않음 -> 리렌더링 X
// false -> props 바뀜 -> 리렌더링 O
if (prevProps.id !== nextProps.id) return false;
if (prevProps.isDone !== nextProps.isDone) return false;
if (prevProps.content !== nextProps.content) return false;
if (prevProps.date !== nextProps.date) return false;
return true; // 위에 걸리지 않으면 true
});
출처
한입 크기로 잘라먹는 리액트