โWhat is useCallback
์ธ์๋ก ์ ๋ฌํ ํจ์๋ฅผ ๊ธฐ์ตํ์ฌ ํด๋น ํจ์๋ฅผ ์ฌ์ฌ์ฉํ๋ค.
์์ ์ฝ๋
export default function Hello() {
const [name, setName] = useState('');
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
const handleClick = () => {
console.log(`handleClick ์์ name ์ ๊ฐ์? ${name}`);
};
useEffect(() => {
console.log('handleOnChange ๋ณ๊ฒฝ!');
}, [handleClick]);
return (
<div>
<input type='text' value={name} onChange={handleOnChange} />
<button type='button' onClick={handleClick}>
Click
</button>
</div>
);
}
์ ์ ๊ฐ ์
๋ ฅํ ๋๋ง๋ค name ์ํ ๊ฐ์ด ๋ฐ๋๊ธฐ ๋๋ฌธ์, ์
๋ ฅํ ๋๋ง๋ค ์ปดํฌ๋ํธ์ ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ๋ค.
๋งค ์
๋ ฅ๋ง๋ค ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋๊ธฐ ๋๋ฌธ์ handleClick ํจ์๋ ๋งค๋ฒ ์ด๊ธฐํ๋๋ค.
handleClick ํจ์๊ฐ ๋งค๋ฒ ์ด๊ธฐํ๋์ด, ํจ์ ๊ฐ์ฒด์ ์ฃผ์๊ฐ์ด ๋ฌ๋ผ์ง๊ธฐ ๋๋ฌธ์, ๋งค ์
๋ ฅ๋ง๋ค useEffect ๊ฐ ์คํ๋๋ค.
handleClick ํจ์๋ฅผ useCallback ์ผ๋ก ๊ฐ์ธ๊ธฐ
export default function Hello() {
const [name, setName] = useState('๊ธฐ๋ณธ ๊ฐ');
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
const handleClick = useCallback(() => {
console.log(`handleClick ์์ name ์ ๊ฐ์? ${name}`);
}, []);
useEffect(() => {
console.log('handleOnChange ๋ณ๊ฒฝ!');
}, [handleClick]);
return (
<div>
<input type='text' value={name} onChange={handleOnChange} />
<button type='button' onClick={handleClick}>
Click
</button>
</div>
);
}
handleClick ํจ์๋ฅผ useCallback ์ผ๋ก ๋ฉ๋ชจ์ด์ ์ด์
ํ๊ณ , ์์กด์ฑ๋ฐฐ์ด์ ๋น๋ฐฐ์ด์ ์ค์ ํ์๋ค.
์
๋ ฅ ๊ฐ์ผ๋ก ์ปดํฌ๋ํธ๊ฐ ๋งค๋ฒ ๋ฆฌ๋ ๋๋ง ๋์ด๋, handleClick ํจ์๋ ๋ณ๊ฒฝ๋์ง ์๋๋ค.
Input ์ ๋ฌธ์๋ฅผ ์
๋ ฅํ ํ์ ๋ฒํผ์ ํด๋ฆญํ๋ฉด, '๊ธฐ๋ณธ ๊ฐ'์ด ์ถ๋ ฅ๋๋ค.
์์กด์ฑ ๋ฐฐ์ด์ ๋น๋ฐฐ์ด์ด ๋ค์ด๊ฐ ์๊ธฐ ๋๋ฌธ์, ์ปดํฌ๋ํธ ๋ ๋๋ง์ ํ ๋ฒ๋ง ํธ์ถ๋๊ณ , ๊ทธ ํ์๋ ์๋ฌด๋ฆฌ ๋ฆฌ๋ ๋๋ง๋์ด๋ handleClick ํจ์๊ฐ ์ด๊ธฐํ๋์ง ์๊ณ , ํด๋น ์ฃผ์ ๊ฐ์ด ๋จ์์๋ค.
useCallback ์์กด์ฑ๋ฐฐ์ด ์์
export default function Hello() {
const [name, setName] = useState('๊ธฐ๋ณธ ๊ฐ');
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
const handleClick = useCallback(() => {
console.log(`handleClick ์์ name ์ ๊ฐ์? ${name}`);
}, [name]);
useEffect(() => {
console.log('handleOnChange ๋ณ๊ฒฝ!');
}, [handleClick]);
return (
<div>
<input type='text' value={name} onChange={handleOnChange} />
<button type='button' onClick={handleClick}>
Click
</button>
</div>
);
}
์
๋ ฅ ๊ฐ์ ๋ฐ๋ผ์ name ์ด๋ผ๋ ์ํ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค.
useCallback์ ์์กด์ฑ ๋ฐฐ์ด์ name ๊ฐ์ ์ค์ ํ์์์ผ๋ก, ์
๋ ฅ ๊ฐ์ ๋ฐ๋ผ์ ํจ์๊ฐ ์ด๊ธฐํ๋๋ค.
๋ฐ๋ผ์ ๋ฒํผ์ ํด๋ฆญํ์ ๋ ์
๋ ฅํ ๊ฐ์ด ๊ทธ๋๋ก ์ฝ์์ ํ์๋๋ค.
์ฌ๊ธฐ๊น์ง ๋ณด๋ฉด useCallback์ ์ฌ์ฉํ ๋์ ์ฌ์ฉํ์ง ์์ ๋์ ํฐ์ฐจ์ด๊ฐ ์์์ ์ ์ ์๋ค.
๊ทธ๋ฌ๋ฉด, ์ด๋ฒคํธ์ ์ํ๋ฅผ ํ๋ ๋ ์ถ๊ฐํด๋ณด์!
์ํ ๊ฐ๊ณผ ์ด๋ฒคํธ ์ถ๊ฐ
export default function Hello() {
const [name, setName] = useState('๊ธฐ๋ณธ ๊ฐ');
const [nickName, setNickName] = useState('');
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
const handleOnChange2 = (e: React.ChangeEvent<HTMLInputElement>) => {
setNickName(e.target.value);
};
const handleClick = useCallback(() => {
console.log(`handleClick ์์ name ์ ๊ฐ์? ${name}`);
}, [name]);
const handleClick2 = useCallback(() => {
console.log(`handleClick ์์ nickName ์ ๊ฐ์? ${nickName}`);
}, [nickName]);
useEffect(() => {
console.log('handleOnChange ๋ณ๊ฒฝ!');
}, [handleClick]);
return (
<div>
<div>
<input type='text' value={name} onChange={handleOnChange} />
<button type='button' onClick={handleClick}>
Click
</button>
</div>
<div>
<input type='text' value={nickName} onChange={handleOnChange2} />
<button type='button' onClick={handleClick2}>
Click
</button>
</div>
</div>
);
}
์๋ก์ด ์ํ ๊ฐ nickName ์ ๋ง๋ค๊ณ ์ด๋ฒคํธ๋ฅผ ์ฐ๊ฒฐํ์ฌ, ์
๋ ฅํด๋ณด์๋ค.
nickName ๊ฐ์ ์๋ฌด๋ฆฌ ๋ณ๊ฒฝํด๋ handleClick ํจ์๋ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ค๋ฅธ ์์ ๋ฅผ ์ดํด๋ณด์
์๋ 2๊ฐ์ ์ปดํฌ๋ํธ๊ฐ ์๋ค.
// /src/component/Hello.tsx
import { useState } from 'react';
import AnotherComponent from './AnotherCount';
export default function Hello() {
const [count, setCount] = useState < number > 0;
const [isDark, setIsDark] = useState < boolean > false;
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) =>
setCount(Number(e.target.value));
const handleDark = () => setIsDark((prev) => !prev);
return (
<div
style={{
background: isDark ? 'black' : 'white',
}}
>
<input type='number' value={count} onChange={handleChange} />
<button type='button' onClick={handleDark}>
Dark-or-White
</button>
<AnotherComponent handleDark={handleDark} />
</div>
);
}
// /src/component/AnotherComponent.tsx
import { useEffect } from 'react';
export default function AnotherComponent({
handleDark,
}: {
handleDark: () => void;
}) {
useEffect(() => {
console.log('Change count in AnotherCount');
}, [handleDark]);
return <div>div</div>;
}
Hello ์ปดํฌ๋ํธ ์์ AnotherComponent ์ปดํฌ๋ํธ๊ฐ ์๋ค.
Input ์์ ์ซ์ ๊ฐ์ ์ฌ๋ ค๋, ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ถ๋ฆฌ์ธ ๊ฐ์ ๋ฐ๊ฟ๋, AnotherComponent ์ useEffect ๋ ๊ณ์ํ์ฌ ํธ์ถ๋๋ค.
count ๊ฐ์ด๋ isDark ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด, ์์ Hello ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋ค.
ํ์์ AnotherComponent ์ useEffect์ ์์กด์ฑ๋ฐฐ์ด์ handleDark ํจ์๊ฐ ์ค์ ๋์ด์๋๋ฐ, count ๋ isDark ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋ ๋ง๋ค, ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๊ธฐ ๋๋ฌธ์, handleDark ํจ์๋ ๊ณ์ํด์ ์ด๊ธฐํ๋๋ ๊ฒ์ด ์์ธ์ด๋ค.
ํด๊ฒฐ์ฑ
์ isDark ํจ์๋ฅผ useCallback์ผ๋ก ๊ฐ์ธ์ฃผ๋ ์ฃผ๊ณ , isDark ๊ฐ์ ์์กด์ฑ๋ฐฐ์ด์ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค.
import { useCallback, useState } from 'react';
import AnotherComponent from './AnotherCount';
export default function Hello() {
const [count, setCount] = useState < number > 0;
const [isDark, setIsDark] = useState < boolean > false;
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) =>
setCount(Number(e.target.value));
const handleDark = useCallback(() => setIsDark((prev) => !prev), [isDark]);
return (
<div
style={{
background: isDark ? 'black' : 'white',
}}
>
<input type='number' value={count} onChange={handleChange} />
<button type='button' onClick={handleDark}>
Dark-or-White
</button>
<AnotherComponent handleDark={handleDark} />
</div>
);
}
Ref
Last updated