React
useCallback() 적용하기
shuai
2025. 2. 5. 17:19
https://ko.react.dev/reference/react/useCallback#usage
useCallback()은 메모이제이션을 도와주는 hook이다. 즉, 복잡한 함수 호출의 결과값을 함수에 저장해놓고, 같은 입력이 반복될 때 저장한 값을 반환하여 속도를 높이는 최적화 기술이다.
Input 디자인시스템을 만들고 있는데, useCallback()을 코드에 한번 적용해보았다. 현재 내가 구현한 코드는 아래와 같다.
// input.stories.tsx
...
export const 입력 = ({placeholder, backgroundColor, outlineColor, variant, full, disabled, clearable}: InputPros) => {
const [text, setText] = useState('')
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setText(e.target.value)
console.log('onChange')
}
return (
<div>
<Input
placeholder={placeholder}
backgroundColor={backgroundColor}
outlineColor={outlineColor}
variant={variant}
full={full}
disabled={disabled}
onChange={handleOnChange}
value={text}
clearable={clearable}
/>
</div>
)
}
// input.tsx
...
export function Input({
placeholder = '',
variant = 'filled',
backgroundColor = 'adaptiveBlue500',
outlineColor,
full = false,
onChange,
value = '',
clearable = false,
...restProps
}: InputProps) {
const clearInput = () => {
if (onChange) {
const event = {target: {value: ''}} as React.ChangeEvent<HTMLInputElement>
onChange(event)
}
}
return (
<div className={cx('input-container', full && 'full')}>
<div className={cx('input-wrapper')}>
<input
placeholder={placeholder}
onChange={onChange}
value={value}
{...restProps}
/>
{value && clearable && (
<button className={cx('clearable-btn')} onClick={clearInput}>
...
</button>
)}
</div>
</div>
)
}
handleOnChange()가 매번 새로운 참조 값을 가지는 이유?
input.stories.tsx에서 이 함수는 useState(setText())를 호출하고 있다. 이때, setText()가 동작하면 컴포넌트가 리렌더링 된다. 그럴때마다 handleOnChange() 함수는 새로운 함수 인스턴스로 생성된다. 또한, 새로운 참조값을 input.tsx에서 정의하고 있는 Input 컴포넌트의 onChange 속성으로 전달하고, Input 컴포넌트는 onChange() 속성이 변경되었다고 인식하고 리렌더링 되는 것이다.
clearInput()이 리렌더링을 유발하는 이유?
Input 컴포넌트가 리렌더링 될 때 마다 clearInput() 함수는 리렌더링 된다.
해결 방법
1. handleOnChange()에 useCallback() 적용
const handleOnChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setText(e.target.value);
console.log('onChange');
}, []);
- 최초 렌더링 시 한 번만 생성
- 입력 필드의 값이 변경되어도 새로운 함수 인스턴스가 생성되지 않음
- Input 컴포넌트의 onChange 속성이 변경되지 않으므로 불필요한 리렌더링 방지
2. clearInput()에 useCallback() 적용
const clearInput = useCallback(() => {
if (onChange) {
const event = { target: { value: '' } } as React.ChangeEvent<HTMLInputElement>;
onChange(event);
}
}, [onChange]);
- 최초 렌더링 시 한 번만 생성, onChange가 변경될 때만 새로 생성
- clearable 버튼의 onClick 속성이 변경되지 않으므로 불필요한 리렌더링 방지