728x90
SMALL
- 이번 글에서는 useCallback에 대해서 이야기해보겠습니다.
useCallback
1) 역할
- useCallback은 React Component에서 메모이제이션된 Callback function을 생성하기 위한 Hook입니다.
- 주로 불필요한 rendering을 방지하고 성능을 최적화하는 데 사용됩니다.
- useCallback을 통해 함수의 참조 동일성을 유지해서 자식 component의 불필요한 re-rendering을 막을 수 있습니다.
2) 동작 방식
- useCallback은 메모이제이션된 callback function을 반환하는데,
- 첫 번째 인자로는 메모이제이션할 callback function을 받습니다.
- 두 번째 인자로 의존성 배열(dependency array)을 받습니다. 이 배열 내의 값들이 변경될 때만 새로운 함수가 생성됩니다.
- 의존성 배열이 변경되지 않으면 이전에 메모이제이션된 function을 반환합니다.
- 빈 배열([ ])을 전달하면 component의 생명주기 동안 항상 동일한 함수 참조를 유지합니다.
- 의존성 배열을 생략하면 매 rendering마다 새로운 함수를 생성하므로 useCallback의 이점이 사라집니다.
3) 간단한 예시 몇 가지!
- Re-rendering 최적화
import React, { useState, useCallback, useRef } from "react";
interface ChildProps {
count: number;
onIncrement: () => void;
onDecrement: () => void;
type: string;
}
const ChildComponent: React.FC<ChildProps> = React.memo(
({ count, onIncrement, onDecrement, type }) => {
const renderCount = useRef(0);
renderCount.current += 1;
return (
<Card>
<CardTitle>{type} useCallback</CardTitle>
<CountDisplay>{count}</CountDisplay>
<ButtonGroup>
<Button onClick={onDecrement}>-</Button>
<Button onClick={onIncrement}>+</Button>
</ButtonGroup>
<RenderCount>Re-rendering: {renderCount.current}</RenderCount>
</Card>
);
}
);
const UseCall: React.FC = () => {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
const [parentRender, setParentRender] = useState(0);
const increment1 = useCallback(() => setCount1((c) => c + 1), []);
const decrement1 = useCallback(() => setCount1((c) => c - 1), []);
const increment2 = () => setCount2((c) => c + 1);
const decrement2 = () => setCount2((c) => c - 1);
return (
<Container>
<Title>useCallback Rendering</Title>
<CardContainer>
<ChildComponent
count={count1}
onIncrement={increment1}
onDecrement={decrement1}
type="With"
/>
<ChildComponent
count={count2}
onIncrement={increment2}
onDecrement={decrement2}
type="Without"
/>
</CardContainer>
<ParentAction onClick={() => setParentRender((p) => p + 1)}>
Parent Component Re-rendering
</ParentAction>
<RenderCount>Parent Re-rendering: {parentRender}</RenderCount>
<Explanation>
위 버튼으로 Parent Component를 Re-rendering 할 수 있어요!
<br />
useCallback을 사용한 Component는 불필요한 Re-rendering을 방지합니다.
</Explanation>
</Container>
);
};
- API 호출 최적화
import React, { useState, useCallback, useEffect } from "react";
const UserSearch: React.FC = () => {
const [userId, setUserId] = useState("");
const [user, setUser] = useState<any>(null);
const [apiCallCount, setApiCallCount] = useState(0);
const fetchUser = useCallback(async () => {
if (userId) {
setApiCallCount((count) => count + 1);
try {
await new Promise((resolve) => setTimeout(resolve, 500));
setUser({
id: userId,
name: `User ${userId}`,
email: "user@example.com",
phone: "010-1234-5678",
});
} catch (error) {
console.error("Error fetching user:", error);
setUser(null);
}
}
}, [userId]);
useEffect(() => {
fetchUser();
}, [fetchUser]);
return (
<Container>
<Title>User Search</Title>
<Input
type="text"
value={userId}
onChange={(e) => setUserId(e.target.value)}
placeholder="Enter user ID"
/>
<Button onClick={fetchUser}>Fetch User</Button>
{user && (
<Result>
<h2>{user.name}</h2>
<p>Email: {user.email}</p>
<p>Phone: {user.phone}</p>
</Result>
)}
<ApiCallCount>API 호출 횟수: {apiCallCount}</ApiCallCount>
</Container>
);
};
- useCallback Hook은 주로 자식 component에 함수를 props로 전달할 때나 useEffect의 의존성으로 함수를 사용할 때 유용합니다.
- 성능 최적화에 도움이 되지만, 모든 함수에 사용하는 것은 오히려 성능을 저하시킬 수 있으므로 적절히 사용해야 합니다.
- 다음 글에서는 useMemo에 대해서 알아보겠습니다.
728x90
LIST
'Projects > Conti:ed' 카테고리의 다른 글
[Conti:ed] 개요 및 index.tsx (6) | 2024.12.18 |
---|---|
[React] useRef (0) | 2024.07.03 |
[React] useEffect (0) | 2024.06.29 |
[React] useState (0) | 2024.06.28 |