컴포넌트를 메모리에 저장한다.
React.memo
는 부모 컴포넌트가 변경될 때 자식 컴포넌트가 바뀐게 없는데 바뀌면서 렌더링이 일어날 경우를 방지하기 위해 사용된다.
아래의 코드를 살펴보면 +버튼과 -버튼을 누를 경우 아래 있는 Box1 컴포넌트도 같이 랜더링 된다.
import React, { useState } from "react";
import Box1 from "./components/Box1"
const boxesStyle = {
display: "flex",
marginTop: "10px",
};
function App() {
console.log("App 컴포넌트가 렌더링되었습니다!");
const [count, setCount] = useState(0);
// 1을 증가시키는 함수
const onPlusButtonClickHandler = () => {
setCount(count + 1);
};
// 1을 감소시키는 함수
const onMinusButtonClickHandler = () => {
setCount(count - 1);
};
return (
<>
<h3>카운트 예제입니다!</h3>
<p>현재 카운트 : {count}</p>
<button onClick={onPlusButtonClickHandler}>+</button>
<button onClick={onMinusButtonClickHandler}>-</button>
<div style={boxesStyle}>
<Box1 />
</div>
</>
);
}
export default App;
이를 방지하기위해 React.memo를 사용하는대 사용방법은 간단하다.
아래 코드에서 export default Box1
하는 곳을
export default React.memo(Box1)
로 변경해 주면 메모리에 저장되어 +,- 버튼을 눌러서 숫자가 바껴도 Box1은 리 렌더링 되지 않는다.
import React from "react";
const boxStyle = {
width: "100px",
height: "100px",
backgroundColor: "#91c49f",
color: "white",
// 가운데 정렬 3종세트
display: "flex",
justifyContent: "center",
alignItems: "center",
};
function Box1() {
console.log("Box1이 렌더링되었습니다.");
return <div style={boxStyle}>Box1</div>;
}
export default React.memo(Box1);
useCallback은 인자로 들어오는 함수 자체를 메모리에 저장한다.
아래 코드를 보면 props를 이용해서 initCount
를 보내주고있습니다. React.memo
가 되어있는 상태에서도 +,- , 초기화
버튼을 누를때마다 Box1 컴포넌트가 리렌더링 됩니다.
그 이유는 불변성에 있습니다. props로 내려주고 있는 함수는
App
컴포넌트가 리 랜더링 될 때 마다 메모리에서 새로운 주소가 할당되어 변경되는 거로 인식되기 때문입니다.
// count를 초기화해주는 함수
const initCount = () => {
setCount(0);
};
return (
<>
<h3>카운트 예제입니다!</h3>
<p>현재 카운트 : {count}</p>
<button onClick={onPlusButtonClickHandler}>+</button>
<button onClick={onMinusButtonClickHandler}>-</button>
<div style={boxesStyle}>
<Box1 initCount={initCount} />
</div>
</>
);
}
function Box1({ initCount }) {
const onInitButtonClickHandler = () => {
initCount();
};
return (
<div style={boxStyle}>
<button onClick={onInitButtonClickHandler}>초기화</button>
</div>
);
}
export default React.memo(Box1)
아래 코드처럼 변경하고 나면 Box1은 다시 관계없이 리 렌더링 되지않습니다.
// 변경 전
const initCount = () => {
setCount(0);
};
// 변경 후
const initCount = useCallback(() => {
setCount(0);
}, []);
값 , value 를 메모리에 저장한다.
아래 코드에서 heavyWork
함수는 단순히 100을 리턴하는 함수이지만 리렌더링 시에 계속 for문 작업을 진행함으로서 계속 느려질수있습니다.
useMemo
를 사용해서 값을 메모리에 저장해두면 바로바로 리 렌더링이 되는걸 볼수있습니다.
import React, { useState, useMemo } from "react";
function HeavyButton() {
const [count, setCount] = useState(0);
const heavyWork = () => {
for (let i = 0; i < 1000000000; i++) {}
return 100;
};
// CASE 1 : useMemo를 사용하지 않았을 때
const value = heavyWork();
// CASE 2 : useMemo를 사용했을 때
// const value = useMemo(() => heavyWork(), []);
return (
<>
<p>나는 {value}을 가져오는 엄청 무거운 작업을 하는 컴포넌트야!</p>
<button
onClick={() => {
setCount(count + 1);
}}
>
누르면 아래 count가 올라가요!
</button>
<br />
{count}
</>
);
}
export default HeavyButton;
useMemo를 너무남용할시 별도의 메모리 확보를 너무 많이 하게 되기 때문에 오히려 성능이 안 좋아질 수 있습니다.