Frontend/React

[React] React - useCallback 사용하기

w00se 2021. 7. 5. 01:17

https://pixabay.com/ko/photos/tv-타워-건물-저녁-6139241/

React의 컴포넌트 안에 로컬 함수를 정의하면 컴포넌트가 다시 렌더링 될 때마다 함수가 새로 만들어진다.

더 자세히 말하면 함수가 새로운 메모리 주소에 다시 만들어 지는 것이다.

useCallback을 사용하면 특정 조건을 만족할 때만 함수를 새로 만들 수 있다.

 

useCallback 이란?

React 공식 문서에 'useCallback은 dependencies(특정 조건)에 의해서만 바뀌는 memoized 된 콜백을 반환한다.'

=> 즉, dependencies가 바뀔 때만 함수가 새로 만들어진다.

 

useCallback에 대한 더 자세한 설명은 아래의 공식 문서에서 확인 가능하다.

https://reactjs.org/docs/hooks-reference.html#usecallback

 

Hooks API Reference – React

A JavaScript library for building user interfaces

reactjs.org

 

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);

 

실행 예시

useCallback 사용 전

 

 

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))