이전에도 React.memo 개념글을 작성한 적이 있는데, https://hello-kk.tistory.com/679
리-렌더링을 막기 위한 방법으로 다시 접근해보니 새로워서 다시 정리했다.
//App.jsx
import { Fragment, useState } from "react";
import Tmp from "./Components/Tmp";
function App() {
const [state, setState] = useState(1);
const handleButton = () => {
setState((prev) => prev + 1);
};
return (
<Fragment>
<div>hi~</div>
<div>{state}</div>
<button onClick={handleButton}>버튼</button>
<Tmp />
</Fragment>
);
}
export default App;
(1) React.memo를 사용하지 않은경우
버튼을 매번 클릭할때마다 console.log()에 'Tmp 컴포넌트'가 클릭 수만큼 출력되어 나온다. => 클릭 수만큼 리-렌더링
//Tmp.jsx
function Tmp() {
console.log("Tmp 컴포넌트");
return <div>hello~</div>;
}
export default Tmp;
(2) React.memo를 사용한 경우
버튼을 매번 클릭하더라도 <Tmp>의 props가 변하지 않았다면 리-렌더링 되지 않는다.
//Tmp.jsx
import React from "react";
function Tmp() {
console.log("Tmp 컴포넌트");
return <div>hello~</div>;
}
export default React.memo(Tmp);
(3) React.memo를 사용했을 때 버튼1과 버튼2로 리-렌더링 관찰하기
- 버튼1의 기능 : App 컴포넌트에서만 사용되는 'state'(변수명) 값만을 변화하여 App컴포넌트를 리-렌더링
- 버튼2의 기능 : App컴포넌트에서 선언한 'cnt'를 Tmp 컴포넌트에 전달하여 리-렌더링
//App.jsx
import { Fragment, useState } from "react";
import Tmp from "./Components/Tmp";
function App() {
const [state, setState] = useState(1);
const [cnt, setCnt] = useState(1);
const handleButton1 = () => {
setState((prev) => prev + 1);
console.log(cnt, "app");
};
const handleButton2 = () => {
console.log(cnt, "app");
setCnt((prev) => prev + 1);
};
return (
<Fragment>
<div>hi~</div>
<div>{state}</div>
<button onClick={handleButton1}>버튼1</button>
<button onClick={handleButton2}>버튼2</button>
<Tmp cnt={cnt} />
</Fragment>
);
}
export default App;
.
//Tmp.jsx
import React from "react";
function Tmp(props) {
const { cnt } = props;
console.log("Tmp 컴포넌트", cnt);
return (
<div>
<div>hello~</div>
<div>{cnt}</div>
</div>
);
}
export default React.memo(Tmp);
자식 컴포넌트에서 props가 변하지 않는 경우 리-렌더링을 막는 방법 : React.Memo.
아무래도 props가 없는 컴포넌트에 주로 쓰일 것 같다. 혹은 상위 컴포넌트에서 빈번하게 랜더링이 발생하는 경우에도.. 그렇지만 props 를 비교하는 과정이 있다고 하니, trade-off를 생각해보아야 할 것 같다.
contextAPI에서는 어떻게 될까 똑같을까?
흠. 신기하게도
ContextAPI 프로바이더 안의 React.memo가 동작하는 방식은 2가지 정도 되는 것 같다. 다른 경우의 수가 있는지는 모르겠지만, 실행해본 결과
(1) 컴포넌트가 useContext()를 이용해서 props를 받는 경우, React.memo로 감싸고 props가 변경되지 않더라도
=> 리-렌더링 된다.
(2) 컴포넌트가 useContext()를 이용해서 props를 받지 않는 경우, React.memo로 감싸면
=> 리-렌더링 되지 않는다.
그런데, 특이하게도
<Provider >
<컴포넌트 1> // React.memo를 사용O, useContext 사용 X => 리-렌더링 X
<컴포넌트 2 /> // React.memo를 사용O, useContext 사용O => 리-렌더링 O
<컴포넌트 1>
<Provider />
컴포넌트 1은 React.memo를 사용하되 useContext를 사용하지 않고,
컴포넌트 2는 React.memo를 사용하면서 useContext를 사용한 경우에
=> 컴포넌트 1은 리-렌더링 되지 않지만, 컴포넌트 2는 리-렌더링 된다.
Provider 컴포넌트가 리-렌더링 되면 useContext()를 받는 컴포넌트는 무조건 리-렌더링 된다. value 가 바뀌지 않더라도.
그런데, useContext를 사용하지 않는 하위 컴포넌트 중 React.memo를 사용했다면 하위 컴포넌트는 리-렌더링 되지 않는다.
React.memo는 어떤 때 써야 하는 걸까? 하는 고민이 생겼는데..
script 문제? paint 문제?
컴포넌트가 하는 일이 많은 경우. 부하가 큰 경우..?
'Front-End > React.js' 카테고리의 다른 글
Virtual DOM (0) | 2023.03.23 |
---|---|
state 란? 무엇인가 . . .🙄 (0) | 2023.03.22 |
state 관리 대상 줄이기를 고민하다가 => useMemo, useCallback까지 (0) | 2023.03.17 |
useState의 setState((prev)=> !prev) (0) | 2023.03.14 |
커스텀 훅 (0) | 2023.03.14 |