7-6. Hooks - useCallback

송한솔·2023년 4월 27일
0

ReactStudy

목록 보기
36/54

useCallback?

useCallback은 useMemo와 상당히 비슷한 함수입니다.

주로 렌더링 성능을 최적화해야 하는 상황에서 사용합니다.
이 Hook을 사용하면 만들어 놨던 함수를 재사용할 수 있습니다.

useMemo에서 생성한 Average.js 컴포넌트를 봅시다.

import { useState, useMemo } from 'react';

const getAverage = numbers => {
    console.log("평균값 계산 중..");
    if(numbers.length === 0) return 0;
    //reduce = 누적 연산(이 경우엔 배열의 모든 요소를 하나의 값(sum)에 누적합니다)
    const sum = numbers.reduce((a,b) => a+b);
    return sum / numbers.length;
};

const Average = () => {

const [list, setList] = useState([]);
const [number, setNumber] = useState('');

const onChange = e => {
    setNumber(e.target.value);
};

const onInsert = e => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
}

const avg = useMemo(()=>getAverage(list), [list]);

    return (
        <div>
            <input value={number} onChange={onChange}/>
            <button onClick={onInsert}>등록</button>
            <ul>
                {list.map((value, index) => (<li key={index}>{value}</li>))}
            </ul>
            <p><b>평균값:</b>{avg}</p>
        </div>
    );
};

export default Average;

onChange와 onInsert라는 함수를 선언했지만,

이렇게 선언한다면 함수가 컴포넌트가 리렌더링될 때마다 onChange와 onInsert함수를 새로 만들어서 사용하게 됩니다.

대부분 이러한 방식에 문제가 없지만, 컴포넌트의 렌더링이 잦거나 렌더링할 컴포넌트 개수가 많아지면 이 부분을 최적화 해주는 것이 좋습니다.

useCallback을 사용하여 최적화해 봅시다.

useCallback 사용하기

수정된 Average.js

import { useState, useMemo, useCallback } from 'react';

const getAverage = numbers => {
    console.log("평균값 계산 중..");
    if(numbers.length === 0) return 0;
    //reduce = 누적 연산(이 경우엔 배열의 모든 요소를 하나의 값(sum)에 누적합니다)
    const sum = numbers.reduce((a,b) => a+b);
    return sum / numbers.length;
};

const Average = () => {

const [list, setList] = useState([]);
const [number, setNumber] = useState('');

// 컴포넌트가 처음 렌더링될 때만 함수 생성
// => 두 번째 파라미터에 공백을 넣을 시 수정없이 계속 재활용 한다는 의미
const onChange = useCallback(e => {
    setNumber(e.target.value);
}, []); 


// number 혹은 list가 변경되었을 때만 함수 생성
const onInsert = useCallback(e => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
}, [number, list]); 

const avg = useMemo(()=>getAverage(list), [list]);

    return (
        <div>
            <input value={number} onChange={onChange}/>
            <button onClick={onInsert}>등록</button>
            <ul>
                {list.map((value, index) => (<li key={index}>{value}</li>))}
            </ul>
            <p><b>평균값:</b>{avg}</p>
        </div>
    );
};

export default Average;

useCallback의 첫 파라미터에는 생성하고 싶은 함수를 넣고

두 번째 파라미터에는 배열을 넣고,
이 배열에는 어떤 값이 바뀌었을 때 함수를 새로 생성해야하는지 명시하면 됩니다.

onChange처럼 비어 있는 배열을 넣게 되면 컴포넌트가 렌더링될 때 만들었던 함수를 계속해서 재사용하게 되며 onInsert처럼 배열 안에 [**number,list]**를 넣게 되면 인풋내용이 바뀌거나 새로운 항목이 추가될 때 새로 만들어진 함수를 사용하게 됩니다.

0개의 댓글