다른 Hook 의 종속성 메모화
컴포넌트 본문에서 직접 생성된 객체에 의존하는 연산이 있다고 가정하자.
function Dropdown({ allItems, text }) {
const searchOptions = { matchMode: 'whole-word', text };
const visibleItems = useMemo(() => {
return searchItems(allItems, searchOptions);
}, [allItems, searchOptions]); // 🚩 주의: 컴포넌트 본문에서 생성된 객체에 대한 종속성
// ...
이렇게 객체에 의존하는 것은 메모이제이션의 목적을 무색하게한다. 컴포넌트가 다시 렌더링 되면 컴포넌트 본문 내부의 모든 코드가 다시 실행되기 때문이다. searchOptions 객체를 생성하는 코드도 다시 렌더링 될때마다 실행된다. searchOptions은 useMemo 호출의 종속성이고 매번 다르기 때문에, React는 종속성이 다른 것을 알고 searchItems을 매번 다시 계산한다.
이 문제를 해결하기 위해 searchOptions 객체 자체를 종속성으로 전달하기 전에 메모해두면 된다.
function Dropdown({ allItems, text }) {
const searchOptions = useMemo(() => {
return { matchMode: 'whole-word', text };
}, [text]); // ✅ text가 변경될 때만 변경
const visibleItems = useMemo(() => {
return searchItems(allItems, searchOptions);
}, [allItems, searchOptions]); // ✅ allItems이나 searchOptions이 변경될 때만 변경
// ...
위의 예제에서 text가 변경되지 않았다면 searchOptions 객체도 변경되지 않는다. 그러나 이보다 더 나은 방법은 searchOptions를 useMemo 계산 함수의 내부에 선언하는 것이다.
function Dropdown({ allItems, text }) {
const visibleItems = useMemo(() => {
const searchOptions = { matchMode: 'whole-word', text };
return searchItems(allItems, searchOptions);
}, [allItems, text]); // ✅ allItems이나 text가 변경될 때만 변경
// ...
이제 연산은 text에 직접적으로 의존한다.
함수 메모화
Form 컴포넌트가 memo로 감싸져 있고 여기에 prop로 함수를 전달하고 싶다고 가정해보자.
export default function Page({ productId, referrer }) {
const handleSubmit = useMemo(() => {
return (orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
};
}, [productId, referrer]);
return <Form onSubmit={handleSubmit} />;
}
{}가 다른 객체를 생성하는 것처럼 function() {}와 같은 함수 선언과 () => {} 같은 표현식은 다시 렌더링 될 때마다 다른 함수를 생성한다. 새로운 함수를 만드는 것 자체는 문제가 되지 않으며 피해야 할 일이 아니다. 그러나 Form 컴포넌트가 메모화 되어 있다면 props가 변경되지 않았을 때 재렌더링 되는 것을 막고싶을 것이다. 항상 다른 prop은 메모이제이션의 목적을 무색하게 만들 수 있다.
useMemo로 함수를 메모하려면 계산 함수에서 다른 함수를 반환해야 한다.
export default function Page({ productId, referrer }) {
const handleSubmit = useCallback((orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
}, [productId, referrer]);
return <Form onSubmit={handleSubmit} />;
}
위 두 예제는 완전히 동일하게 동작한다. useCallback의 유일한 장점은 내부에 중첩된 함수를 추가로 작성하지 않아도 된다는 것이다.
'React 공식문서 스터디' 카테고리의 다른 글
useMemo, useCallback 발표자료 (0) | 2024.06.21 |
---|---|
useCallback (1) (0) | 2024.06.18 |
useMemo (1) (0) | 2024.06.17 |
useEffect, useLayoutEffect 발표자료 (0) | 2024.06.14 |
useLayoutEffect (2) | 2024.06.11 |