React의 컴포넌트 안에 로컬 함수를 정의하면 컴포넌트가 다시 렌더링 될 때마다 함수가 새로 만들어진다.
더 자세히 말하면 함수가 새로운 메모리 주소에 다시 만들어 지는 것이다.
useCallback을 사용하면 특정 조건을 만족할 때만 함수를 새로 만들 수 있다.
useCallback 이란?
React 공식 문서에 'useCallback은 dependencies(특정 조건)에 의해서만 바뀌는 memoized 된 콜백을 반환한다.'
=> 즉, dependencies가 바뀔 때만 함수가 새로 만들어진다.
useCallback에 대한 더 자세한 설명은 아래의 공식 문서에서 확인 가능하다.
https://reactjs.org/docs/hooks-reference.html#usecallback
useCallback은 최적화된 자식 컴포넌트로 전달하는 함수에 주로 사용된다.
여기서 최적화된 자식 컴포넌트랑 불필요한 렌더링을 방지한 컴포넌트로 함수형 컴포넌트의 경우 React.memo가 사용된 컴포넌트이다.
useCallback 사용 예시
useCallback 사용 전 코드
PracticeMemo.tsx
: 하나의 input 엘리먼트와 PracticeMemoResetButton 자식 컴포넌트를 가지고 있다. PracticeMemoResetButton으로 onReset 함수를 전달한다.
import React, { useState } from 'react';
import PracticeMemoResetButton from '../components/PracticeMemoResetButton';
interface PracticeMemoProps {
}
function PracticeMemo(props: PracticeMemoProps) {
const [ input, setInput ] = useState<string>("");
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInput(event.target.value);
}
const onReset = () => {
setInput("");
}
return (
<div>
<div>
<input value={input} onChange={onChange}/>
</div>
<PracticeMemoResetButton onReset={onReset}/>
</div>
)
}
export default PracticeMemo;
PracticeMemoResetButton.tsx
: PracticeMemo.tsx의 자식 컴포넌트이다. 리렌더링 될 때마다 문구가 출력되도록 설정했다.
import React, { useEffect } from 'react';
interface PracticeMemoResetButtonProps {
onReset: () => void,
}
function PracticeMemoResetButton (props: PracticeMemoResetButtonProps) {
const { onReset } = props;
useEffect(()=>{
console.log("리렌더링 됨");
});
return (
<button style={{ marginTop: 20, }} onClick={onReset}>
리셋
</button>
)
}
export default React.memo(PracticeMemoResetButton);
실행 예시
onChange 함수에 의해 input의 state가 변경되고 컴포넌트가 리렌더링 될 때마다 onReset 함수도 재생성된다.
기능이 동일한 함수지만 주소 값이 변경됐음으로 PracticeMemoResetButton(자식 컴포넌트)에서는 props가 변경된 걸로 간주한다.
따라서 PracticeMemoResetButton(자식 컴포넌트)가 리렌더링 된다.
useCallback 사용 후 코드
PracticeMemoResetButton.tsx
import React, { useState, useCallback } from 'react'; // useCallback import
import PracticeMemoResetButton from '../components/PracticeMemoResetButton';
interface PracticeMemoProps {
}
function PracticeMemo(props: PracticeMemoProps) {
const [ input, setInput ] = useState<string>("");
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInput(event.target.value);
}
const onReset = useCallback(() => { // onReset 함수에 useCallback 적용
setInput("");
}, []);
return (
<div>
<div>
<input value={input} onChange={onChange}/>
</div>
<PracticeMemoResetButton onReset={onReset}/>
</div>
)
}
export default PracticeMemo;
실행 예시
참고 자료
https://reactjs.org/docs/react-api.html#reactmemo - React 공식 문서
https://react.vlpt.us/basic/18-useCallback.html - 벨로퍼트와 함께하는 모던 리액트(18. useCallback 을 사용하여 함수 재사용하기)
https://velog.io/@yejinh/useCallback과-React.Memo을-통한-렌더링-최적화 - yejinh.log(useCallback과 React.Memo을 통한 렌더링 최적화)
https://pks2974.medium.com/react-의-성능을-조금-이라도-올려보자-performance-optimize-f1a51b8c406c - 박성룡 ( Andrew park )(React 의 성능을 조금 이라도 올려보자 (Performance Optimize))
'Frontend > React' 카테고리의 다른 글
[React] 리액트 파일 확장자를 jsx로 하는 이유 (0) | 2022.05.04 |
---|---|
[React] redux 정리 (0) | 2021.09.03 |
[React] React - React.memo로 렌더링 최적화 (0) | 2021.07.05 |