useCallback? ๐ค
const memoizedCallback = useCallback(() => { doSomething(a, b);}, [a, b]);
๋ฉ๋ชจ์ด์ ์ด์ ๋ ์ฝ๋ฐฑ์ ๋ฐํํฉ๋๋ค.
useCallback์ useMemo์ ๋น์ทํ Hook ์
๋๋ค. ๐ต
ํฐ ์ฐจ์ด์ ์ useMemo ๋ ๊ฐ์ ๊ธฐ์ต(๋ฉ๋ชจ๋ฆฌ์ ์ด์
)ํ์ง๋ง useCallback ์ ํจ์๋ฅผ ๊ธฐ์ตํ๋ ๊ฒ์ด ํฐ ์ฐจ์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค.
์์ ์ฝ๋
const ComponentThatRendersOften = ({ cb1, cb2 }) => {
const [state, setState] = useState(...);
const doSomething = () => {
// ์๋์ง๊ฐ ๋ง์ด ์๋ชจ๋๋ ์ฐ์ฐ
...
setState(...);
cb1();
};
return (
<button onClick={doSomething} />
);
};์ปดํฌ๋ํธ๊ฐ ๋๋๋ง๋ ๋ ๋ง๋ค ์๋์ง๊ฐ ๋ง์ด ์๋ชจ๋๋ doSomething ํจ์๋ฅผ ๋ค์ ์ ์ธํฉ๋๋ค.
์์ ์ปดํฌ๋ํธ์ ์ค์ฝํ ๋ฐ์ผ๋ก ํจ์๋ฅผ ์ฎ๊ธฐ๋ ๋ฐฉ๋ฒ์ด ์์ง๋ง ๊ทธ๋ด ๊ฒฝ์ฐ ํจ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋งค๋ฒ ๋๊ฒจ์ค์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋
์ฑ์ด ๋จ์ด์ง๊ฒ ๋ฉ๋๋ค.
const ComponentThatRendersOften = ({ cb1, cb2 }) => {
const [state, setState] = useState(...);
const doSomething = useCallback(() => {
// ์๋์ง๊ฐ ๋ง์ด ์๋ชจ๋๋ ์ฐ์ฐ
...
setState(...);
cb1();
}, [cb1]);
return (
<button onClick={doSomething} />
);
};์ด๋ฌํ ์ํฉ์์ useCallback ํ
์ ์ด์ฉํ๊ฒ ๋๋ฉด deps ๋ฐฐ์ด์ ๋ค์ด๊ฐ๋ ๋ณ์๊ฐ ๋ณํ์ง ์๊ฒ ๋๋ฉด ํด๋น ํจ์๋ฅผ ์ฌ์ ์ธํ์ง ์๊ฒ ๋ฉ๋๋ค!
โ ์ฃผ์์ฌํญ
๋ง์ฝ์ deps ๋ฐฐ์ด ์์ ํจ์์์ ์ฌ์ฉํ๋ ๊ฐ์ ๋ฃ์ง ์๊ฒ ๋๋ค๋ฉด, ํจ์ ๋ด์์ ํด๋น ๊ฐ๋ค์ ์ฐธ์กฐํ ๋ ๊ฐ์ฅ ์ต์ ๊ฐ์ ์ฐธ์กฐ ํ ๊ฒ์ด๋ผ๊ณ ๋ณด์ฅํ ์ ์์ต๋๋ค. โ (ํด๋น ๊ฐ์ด ์ ๋ฐ์ดํธ๊ฐ ๋์๋์ง deps ๋ฐฐ์ด์์ ํ์ธํ๋ฏ๋ก)
์ต์ ํ?
์์ ๊ฐ์ด useCallback ๊ฐ ๋ฐํํ๋ ๋ฉ๋ชจ์ด์ ์ด์
๋ ํจ์๋ฅผ ์ด์ฉํ๋ฉด ์ปดํฌ๋ํธ์ ์ต์ ํ๋ฅผ ์ด๋ฃฐ์ ์๊ฒ ๋์ง๋ง
์ค์ ๋ก ์ปดํฌ๋ํธ๊ฐ ๋๋๋ง๋ ๋, ํจ์ ์ ์ธ๊ณผ ๊ด๋ จ๋ ๊ฒ์ ์ฑ๋ฅ ์ต์ ํ์ ํฐ ๋ฌธ์ ๊ฐ ๋์ง๋ ์๋ค๊ณ ํฉ๋๋ค..
๊ทธ๋ ๋ค๋ฉด useCallback์ ์ด๋ป๊ฒ ์ธ ๋ ์๋ฏธ๊ฐ ์์๊น์? ๐
ํจ์์ ๋๋ฑ์ฑ
> const add1 = () => x + y;
undefined
> const add2 = () => x + y;
undefined
> add1 === add2
falseJavaScript์์๋ ํจ์์ ๋๋ฑํจ ๋น๊ต๋ ์ ๊ฒฐ๊ณผ๊ฐ ๋์ถ๋ฉ๋๋ค. ํจ์๋ ๊ฐ์ฒด ์ทจ๊ธ์ ํ๊ธฐ ๋๋ฌธ์ ํจ์ ๋น๊ต์ ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ์ํ ์ฐธ์กฐ ๋น๊ต๊ฐ ์ผ์ด๋๊ธฐ ๋๋ฌธ์
๋๋ค.
(๊ฒฐ๊ตญ ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋๋ฏ๋ก ๋๋ฑ์ฑ โ)
๋๋ฑ์ฑ ๋ฌธ์
์ค์ ์ฝ๋์์๋ ๋๋ฑ์ฑ์ด ๋ฌด์จ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ๊น์?
function Profile({ userId }) {
const [user, setUser] = useState(null);
const fetchUser = () =>
fetch(`https://api/users/${userId}`)
.then((response) => response.json())
.then(({ user }) => user);
useEffect(() => {
fetchUser().then((user) => setUser(user));
}, [fetchUser]);
}์์ ๊ฐ์ ์ฝ๋์์๋ ์๋์ ๊ฐ์ด ์ ์ฐจ๊ฐ ์ด๋ฃจ์ด์ง๋๋ค.
- ์ปดํฌ๋ํธ ๋๋๋ง ๊ณผ์ ์์
fetchUserํจ์๊ฐ ์ ์ธ๋ฉ๋๋ค. uesEffectํ ์ผ๋ก ์ธํfetchUserํจ์๊ฐ ์คํ์ด ๋ฉ๋๋ค.- ํด๋น ํจ์์์
user state๋ฅผ ๋ณํํฉ๋๋ค. - ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋๋๋ง ๋ฉ๋๋ค. (state ๋ณํ๋ก ์ธํ)
- ์ปดํฌ๋ํธ ๋๋๋ง ๊ณผ์ ์์
fetchUserํจ์๊ฐ ์ ์ธ๋ฉ๋๋ค. (๋๋ฑ์ฑ ๋ฌธ์ ๋ก ๋ค๋ฅธ ํจ์ ์ทจ๊ธ) uesEffectํ ์ผ๋ก ์ธํfetchUserํจ์๊ฐ ์คํ์ด ๋ฉ๋๋ค....๋ฌดํ๋ฃจํ ๐คช
๋๋ฑ์ฑ ๋ฌธ์ ๋ก ๋ฌดํ๋ฃจํ๊ฐ ๋ฐ์ํ๊ณ ์์ต๋๋ค โ๏ธ
๋๋ฑ์ฑ ๋ฌธ์ ํด๊ฒฐ (useCallback)
function Profile({ userId }) {
const [user, setUser] = useState(null);
const fetchUser = useCallback(
() =>
fetch(`https://api/users/${userId}`)
.then((response) => response.json())
.then(({ user }) => user),
[userId],
);
useEffect(() => {
fetchUser().then((user) => setUser(user));
}, [fetchUser]);
}์ด๋ฌํ ์ํฉ์์ useCallback ์ ์ฌ์ฉํฉ์๋ค!
- ์ปดํฌ๋ํธ ๋๋๋ง ๊ณผ์ ์์
fetchUserํจ์๊ฐ ์ ์ธ๋ฉ๋๋ค. uesEffectํ ์ผ๋ก ์ธํfetchUserํจ์๊ฐ ์คํ์ด ๋ฉ๋๋ค.- ํด๋น ํจ์์์
user state๋ฅผ ๋ณํํฉ๋๋ค. - ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋๋๋ง ๋ฉ๋๋ค. (state ๋ณํ๋ก ์ธํ)
- ์ปดํฌ๋ํธ ๋๋๋ง ๊ณผ์ ์์
fetchUserํจ์๊ฐ ์ ์ธ๋์ง ์์ต๋๋ค. (useCallback์ deps ๋ฐฐ์ด ๋ณํ๊ฐ ์์ผ๋ฏ๋ก ๊ธฐ์กด์ ์๋ ํจ์ ์ฌ์ฌ์ฉ!)