useMemo
값의 연산 결과를 Memoization하여, 불필요한 재계산을 방지하는 훅
* Memoization?
동일한 값을 리턴하는 함수를 반복적 호출할 경우
맨 처음 계산 할때 메모리에 저장해뒀다 필요할때마다 다시 계산이 아니라 메모리에서 꺼내 재사용하는것
왜 필요한가?
함수형 컴포넌트도 함수.
함수형 컴포넌트 렌더링 -> 컴포넌트 함수 호출 -> 내부 모든 변수 초기화
만약 state 와 props의 변화로 인해 수많은 렌더링을 거친다면 렌더링 될때마다 변수가 초기화가 됨
function calculate(){
return 1
}
function MyComponent(){
const value = calculate();
return <div>{value}</div>
}
렌더링 마다 value 변수 초기화, calculate() 함수 호출 -> 비효율적
! useMemo 값 재활용하기 위해서 따로 메모리를 소비해서 저장하기 때문에 남용시 성능에 좋지않아 필요시 적절히 사용!
*React.memo vs. useMemo
| React.memo | 컴포넌트 | 불필요한 컴포넌트 재렌더링 방지 | props 변경x -> 렌더링x | 같은 props로 렌더링 결과가 같을 때 사용 |
| useMemo | 값 (변수) | 연산 비용이 큰 값을 메모이제이션 | 의존성 배열 값 변경x -> 이전 값 재사용 | 비싼 연산 결과를 저장할 때 사용 |
구조
const value = useMemo(() => {
return calculate();
}, [item])
- 첫 번째 인자: 메모이제이션할 값을 반환하는 함수
- 두 번째 인자: 의존성 배열로, 배열 안의 값이 변경될 때만 첫 번째 인자 호출
- 빈 배열일 경우: 컴포넌트가 마운트시만 값을 계산하고, 이후에는 메모이제이션된 값만을 재사용
사용
const calculate = (num) => {
console.log("무거운 작업");
for (let i = 0; i < 99999999; i++) {}//딜레이
return num + 10000;
}
function App() {
const [num, Setnum] = useState(1);
const result = calculate(num);
const [render, SetRender] = useState();
return (
<div>
<input type="number" value={num} onChange={(e)=>Setnum(parseInt(e.target.value))} />
<span> + 10000 = {result}</span>
<div>
<button onClick={()=> SetRender(!render)}>렌더</button>
</div>
</div>
);
}

이경우 App 컴포넌트가 렌더링때마다 result 변수 초기화, calculate함수가 호출됨
그러면 num 변경에만 calculate함수 불리게 해보자
//const result = calculate(num);
const result = useMemo(()=>{
return calculate(num);
}, [num])

좀더 알아보자
function App() {
const [render, setRender] = useState();
const [prove, setProve] = useState(false);
const result = prove? "진실" : "거짓";
useEffect(() => {
console.log("useEffect 호출");
}, [result]);
return (
<div>
<div>
<button onClick={()=>setRender(!render)}>렌더</button>
</div>
<hr />
<p>진혹거 : {result}</p>
<button onClick={() => setProve(!prove)}>변경!</button>
<p></p>
</div>
);
}

이 경우에는 result 변수 변경시에만 콘실이 찍힘
그렇다면 객체일 경우에는?
function App() {
const [render, setRender] = useState();
const [prove, setProve] = useState(false);
//const result = prove? "진실" : "거짓";
const result = {
first: prove? "진실" : "거짓",
};
useEffect(() => {
console.log("useEffect 호출");
}, [result]);
return (
<div>
<div>
<button onClick={()=>setRender(!render)}>렌더</button>
</div>
<hr />
<p>진혹거 : {result.first}</p>
<button onClick={() => setProve(!prove)}>변경!</button>
<p></p>
</div>
);
}

result 변수 변경하지 않았음에도 콘솔이 찍힘
왜?
원시가 아닌 객체타입은 주소값을 저장하는데 똑같아 보이는 형태여도 주소값이 다르면 다른 객체임
//원시타입
const one = 1;
const one2 = 1;
console.log(one === one2) //true
//객체타입
const one = { 1:1 };
const one2 = { 1:1 };
console.log(one === one2) //false
App함수가 호출되면서 형태가 똑같이 생겼지만 주소값이 다른 객체를 할당받았기때문!
주소가 변경되지않도록 해보자
//const result = prove? "진실" : "거짓";
// const result = {
// first: prove? "진실" : "거짓",
// };
const result = useMemo(()=>{
return {first: prove? "진실" : "거짓"}
},[prove])'React' 카테고리의 다른 글
| [React] TanStack Query(React Query) (0) | 2024.12.10 |
|---|---|
| [React] React with Typescript (0) | 2024.12.05 |
| [React] useRef (0) | 2024.12.02 |
| [React] Styled-Components에서 애니메이션, 테마 (0) | 2024.11.28 |
| [React] Styled Components (0) | 2024.09.24 |