728x90
반응형
✔️useCallback이란?
- useCallback은 함수를 메모이제이션합니다. 주어진 종속성 배열이 변경되지 않으면, 동일한 함수 인스턴스를 반환합니다. 이는 컴포넌트가 불필요하게 다시 렌더링되는 것을 방지하는 데 도움을 줍니다.
- 언제 사용: 컴포넌트가 자주 다시 렌더링되면서 동일한 함수가 다시 생성되는 것을 피하고 싶을 때, 특히 자식 컴포넌트에 콜백 함수를 props로 전달할 때 사용합니다.
usememo랑 너무 헷갈렸는데 둘 다 비슷하긴 하지만 usememo는 특정 결과값을 재사용하는 반면, usecallback은 특정 함수를 새로 만들지 않고 다시 재사용하는 것이다.
1. useCallback의 구조
import React, { useState, useCallback } from 'react';
function Button({ onClick, label }) {
console.log('Button rendered!');
return <button onClick={onClick}>{label}</button>;
}
function ParentComponent() {
const [count, setCount] = useState(0);
// useCallback을 사용하여 콜백 함수를 메모이제이션
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []); // 종속성 배열이 비어있으므로 처음에만 생성되고 이후에는 재사용됨
return (
<div>
<Button onClick={handleClick} label="Increment" />
<p>Count: {count}</p>
</div>
);
}
export default ParentComponent;
ParentComponent가 다시 렌더링되더라도 handleClick 함수는 새로 생성되지 않으며, 동일한 함수 인스턴스가 자식 컴포넌트 Button에 전달됩니다. 이로 인해 Button 컴포넌트는 onClick prop이 변경되지 않았다고 판단해 불필요한 렌더링을 방지할 수 있습니다.
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<ChildComponent onClick={handleClick} />
</div>
);
}
function ChildComponent({ onClick }) {
return (
<button onClick={onClick}>Click me</button>
);
}
handleClick 함수가 ParentComponent 컴포넌트에서 생성되어 ChildComponent 컴포넌트에 props로 전달.
만약 useCallback을 사용하지 않으면 ParentComponent가 리렌더링 될 때마다 handleClick 함수가 새로 생성됩니다. 이 경우 ChildComponent는 onClick props가 변경되었으므로 불필요한 리렌더링이 발생하게 되고 이를 방지하기 위해 useCallback을 사용하여 handleClick 함수를 메모이제이션함
💡 메모이제이션 이란?
이전에 계산한 값을 메모리에 저장해두고, 동일하게 다시 사용할 수 있는 곳에서 재사용하여 반복적으로 발생하는 계산의 리소스를 줄이는 기법
언제 useCallback을 사용하는 것이 최적화에 도움이 될까?
- 자식 컴포넌트에 함수를 전달할 때
- 문제: 자식 컴포넌트가 부모 컴포넌트로부터 받은 함수가 변경될 때마다 다시 렌더링될 수 있습니다. 특히, 자식 컴포넌트가 React.memo로 최적화되어 있거나, shouldComponentUpdate 메소드를 사용하는 경우, 자식 컴포넌트는 props가 변경될 때만 업데이트됩니다.
- 해결: useCallback을 사용하여 함수의 인스턴스를 메모이제이션하고, 자식 컴포넌트가 이전과 동일한 함수를 받을 수 있도록 합니다. 이렇게 하면 불필요한 렌더링을 방지할 수 있습니다.
import React, { useState, useCallback } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return <ChildComponent onClick={handleClick} />;
}
const ChildComponent = React.memo(({ onClick }) => {
console.log('ChildComponent re-rendered');
return <button onClick={onClick}>Click me!</button>;
});
2.자주 호출되는 함수가 있을 때
- 문제: 함수가 자주 호출되거나 복잡한 로직을 포함하고 있다면, 매번 새로 생성되면 성능에 영향을 줄 수 있습니다.
- 해결: useCallback을 사용해 함수를 메모이제이션하면, 함수가 동일한 인스턴스를 유지하게 되어 불필요한 재생성을 막을 수 있습니다.
import React, { useState, useCallback } from 'react';
function ExpensiveComponent() {
const [value, setValue] = useState(0);
const expensiveFunction = useCallback(() => {
// 복잡한 계산
console.log('Expensive function called');
}, []);
return (
<div>
<button onClick={expensiveFunction}>Run Expensive Function</button>
<p>Value: {value}</p>
</div>
);
}
3. useEffect와 같이 사용해 컴포넌트 최적화 하는 경우
import React, { useCallback, useEffect, useState } from "react";
function ExampleComponent(props) {
const [data, setData] = useState([]);
const fetchData = useCallback(async () => {
const response = await fetch("https://example.com/data");
const data = await response.json();
setData(data);
}, []);
useEffect(() => {
fetchData();
}, [fetchData]);
return (
<div>
{data.map((item) => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
export default ExampleComponent;
728x90
반응형
'React' 카테고리의 다른 글
[React] Props로 전달되는 문자열 줄바꿈 하기 (0) | 2024.09.26 |
---|---|
[React]페이지 이탈 시 확인 모달창 띄우기 (0) | 2024.09.13 |
[React] useMemo (2) | 2024.09.03 |
[React] useContext api (0) | 2024.08.27 |
[React]useReducer (0) | 2024.08.20 |