useMemo
- 계산 비용이 높은 연산 결과 "값"을 메모이제이션 함.
- 해당 값이 변경되지 않는 한 다시 계산하지 않아, 렌더링 중에 불필요한 계산을 방지함
- 탑레벨에서 한번 호출되야 함. (hook은 무조건 한번은 호출되야 해서)
- 형태
const memoizedValue = useMemo(() => {
return computeExpensiveValue(a, b); // 계산 비용이 높은 연산 또는 값
}, [a, b]);
- 사용 : 복잡한 계산 처럼 비용이 높은 연산을 피하고 싶을때 사용함.
✅ calculateValue
- 초기 렌더시 한번 호출됨
- 순수 함수여야 함
- 인자를 받지 않음 ( useMemo( ( ) => ), []);
- 캐시하길 원하는 값을 계산하는 함수
- 캐시하길 원하는 값을 반환해야 함
- dependencies값이 바뀌지 않으면 같은 값을 다시 리턴한다.
✅ dependencies
- [dep1, dep2, dep3]
- Object.js()로 이전 이후 값이 같은지 여부를 판단함. (referrence type의 경우는 참조값이 같은지를 판단함)
-
✅ return
- 콜백함수를 호출한 결과를 반환
useCallback
- "함수"를 메모이제이션 함
- 형태
const memoizedCallback = useCallback(
() => {doSomething(a, b)}, // 콜백 함수
[a, b], // dependency
);
- 사용 : 주로 자식 컴포넌트에 props 전달로 인해, 함수가 불필요하게 다시 생성되는 것을 방지할 때 쓰임
✅ fn
- 인자를 받을 수 있음 ( useCallback( (arguments) => ), []);
- 초기 렌더시 함수가 반환된다. 함수가 호출되는 것은 아님!
- 함수가 호출되진 않으므로, 함수 호출 시기와 호출 여부를 직접 결정할 수 있음
✅ dependencies
- Object.js()로 이전 값과 비교함
- 콜백함수 안에서 참조하고 있는 state나 props가 될 확률이 높으나, 절대적인건 아님
✅ return
- 이전 함수와 다른 메모리 주소를 갖는 새로운 함수를 반환함.
💡 useEffect와의 차이
useMemo나 useEffect나 둘다 처음 렌더시 한번 실행되고, dependency 변경이 있을때 동작하게 되는데
이 둘의 차이가 뭔지 헷갈림
간단히 정리하자면
- useMemo : 값이 반환됨
- useCallback: 함수가 반환됨
- useEffect : 함수가 실행될 뿐임.
※ useEffect
- 사용
- 비동기 작엄, 부수 효과를 처리하기 위한 훅, 컴포넌트 렌더링 외부에서 발생하는 작업들을 처리함
- 데이터 패칭, 네트워크 요청 등과 같은 비동기 작업, dom 조작을 다룰 떄
- 실행 시점
- 컴포넌트가 렌더링 완료된 후에 DOM이 업데이트 된 직후에 실행됨.
- 렌더링 완료된 후에 비동기 작업이나 특정 효과를 수행할 때 사용됨
💡 useMemo, useCallback의 dependency가 빈배열 이라면?
: 처음 렌더시 한번만 실행된 뒤, 다시 실행되지 않고 이전에 생성된 값을 계속 재사용함
💡 예제 코드
import { useCallback, useMemo, useState } from "react";
const getAverage = (list) => {
console.log("평균 계산");
if (list.length === 0) return 0;
return list.reduce((acc, cur) => +acc + +cur, 0) / list.length;
};
function Average() {
const [inputValue, setInputValue] = useState("");
const [valueList, setValueList] = useState([]);
const onChange = useCallback((e) => setInputValue(e.target.value), []); // useCallback는 인자 받을 수 있음
const onClick = useCallback(() => {
const updateList = valueList.concat(inputValue);
setValueList(updateList);
setInputValue("");
}, [inputValue, valueList]);
// onClick함수는 inputValue와 valueList를 조회해서 새 list를 생성하기 때문에, dependency에 두 state값이 포함되야함.
return (
<>
<input type="number" value={inputValue} onChange={onChange} />
<button type="button" onClick={onClick}>
등록
</button>
<ul>
{valueList?.map((v, index) => {
return <li key={index}>{v}</li>;
})}
</ul>
<b>평균값 : {useMemo(() => getAverage(valueList), [valueList])}</b> {/* useMemo는 인자 받을 수 없음 */}
</>
);
}
export default Average;
'프론트엔드 > React' 카테고리의 다른 글
Custom React 구현하기 (2) | 2024.12.22 |
---|---|
useState 의 setState는 비동적으로 동작 (0) | 2024.05.06 |
[TIL] React router6 (0) | 2023.09.17 |
[TIL] Style-component (0) | 2023.09.17 |
a태그와 router-link 차이(spa) (0) | 2023.06.30 |