*useMemo
와 useCallback
은 이전 값을 기억해서 성능을 최적화하는 용도로 사용된다.*
useMemo 훅은 계산량이 많은 함수의 반환값을 재활용하는 용도로 사용된다.
import React, {useMemo} from 'react';
import { runExpensiveJob } from './util';
function MyComponent({v1, v2}) {
const value = useMemo(() => runExpensiveJob(v1,v2), [v1, v2]);
return <p>{`value is ${value}`}</p>;
}
useCallback 은 리액트의 렌더링 성능을 위해 제공되는 훅이다. 컴포넌트가 렌더링 될 때마다 새로운 함수를 생성해서 자식 컴포넌트의 속성값(prop) 으로 입력하는 경우가 많다.
import React, {useSatate} from 'react';
import {saveToServer} from './api';
import UserEdit from './UserEdit';
function Profile(){
const [name, setName] = useState('');
const [age, setAge] = useState(0);
return (
<div>
<p>{`name is ${name}`}</p>
<p>{`age is ${age}`}</p>
<UserEdit
onSave={() => saveToServer(name, age)}
setName={setName}
setAge={setAge}
/>
</div>
);
}
*Profile
컴포넌트가 렌더링될 때마다 UserEdit
컴포넌트의 onSave
prop으로 새로운 함수가 선언된다. 따라서 UserEdit
컴포넌트에서 React.memo
를 사용해도 onSave
prop이 항상 변경되고 그 때문에 불필요한 렌더링이 발생한다.*
*useCallback
훅을 사용하면 불필요한 렌더링을 막을 수 있다.*
function Profile(){
const [name, setName] = useState('');
const [age, setAge] = useState(0);
const onSave = useCallback(() => saveToServer(name, age), [name, age]);
return (
<div>
<p>{`name is ${name}`}</p>
<p>{`age is ${age}`}</p>
<UserEdit onSave={onSave} setName={setName} setAge={setAge} />
</div>
);
}
이전에 onSave
속성값으로 전달했던 것과 같은 함수를 useCallback
훅의 첫 번째 매개변수로 입력한다. useCallback
훅의 두 번째 매개변수는 의존성(dependency) 배열이다. 의존성 배열이 변경되지 않으면 이전에 생성한 함수가 재사용된다. 따라서 name
과 age
가 변경되지 않으면, UserEdit
컴포넌트의 onSave
prop으로 항상 같은 함수가 전달된다.
( state의 함수(setName, setAge)는 useCallback 없이도 같은 주소의 함수로 취급된다. )