지난 시간에는 React Hook 중에서 useContext, useRef, useMemo를 알아보았다.
이번 시간에는 useMemo와 유사한 Reac.memo에 대해 알아보고 비교하는 시간을 가질 것이다.
그리고 useCallback을 통해서 또 한번 최적화를 배워 볼 것이다.
참고 사이트는 다음과 같다.
출처 :
https://ko.reactjs.org/docs/react-api.html
https://react.vlpt.us/basic/19-React.memo.html
https://ko.reactjs.org/docs/hooks-reference.html#usecallback
https://www.daleseo.com/react-hooks-use-callback/
https://cocoon1787.tistory.com/798
1. React.memo 사용하기
지난 시간에 이어서 React.memo를 사용해서 좀 더 최적화를 할 것이다.
지난 시간에 코드를 잠시 위치만 수정했다.
App.js
import React from "react";
import "./App.css";
import Clock from "./Clock";
import Count from "./Count";
import Header from "./Header";
export const UserContext = React.createContext();
function App() {
let name = "키메라 끼에ㅔ엥ㄱ";
let state = {
result: "result",
text: "text",
name: "thelovemg",
};
return (
<UserContext.Provider value={state}>
<div className="App">
<Header />
<h2>
<Clock />
<Count />
</h2>
<header className="App-header">hello React! with... {name}</header>
</div>
</UserContext.Provider>
);
}
export default App;
Header.js
import { useContext, useEffect, useRef, useState } from "react";
import { UserContext } from "./App";
import DataList from "./DataList";
const Header = () => {
const [datas, setDatas] = useState([
{
name: "test1",
seq: 123,
},
{
name: "test2",
seq: 122,
},
{
name: "test4",
seq: 124,
},
]);
const { text, name } = useContext(UserContext);
const [resultStr, setResultStr] = useState("");
const addTagContent = useRef("");
useEffect(() => {
addTagContent.current = resultStr;
}, [resultStr]);
return (
<div>
<div>
<h1>{resultStr}</h1>
<button
onClick={() => {
setResultStr((c) => c + "test");
}}
>
add string to first tag... :
</button>
<DataList datas={datas} />
</div>
<br />
header : {text} & {name}
</div>
);
};
export default Header;
이를 실행시키고 버튼을 클릭해서 내용을 추가하도록 하겠다.
필자는 "add string to first tag" 버튼을 클릭했는데 여러 곳에서 색이 변하는 것을 확인할 수 있다.
나는 버튼만 눌럿으면 버튼 위 태그에 내용만 추가되면 될 거 같은데 왜 DataList component가 rerendering 되는 것인가?
그렇다. App.js에 내용이 어찌되었든 변하는 상황이기 때문에 현재의 상황에서는 어찌되었든 내용이 변했으니 전부 다 그려버리는 것이다.
이렇게 되면 사소한 것 하나라도 수정이 일어난다면 하나의 컴포넌트에 포함된 모든 것이 rerendering되어버리니 성능에 악영향을 미칠 수 있다.
그렇기 때문에 React.memo를 이용해야 한다.
React.memo를 이용해서 component를 재사용 하도록 하겠다.
그럼 한 번 사용해 볼까? 휘리릭~!
사용법은 간단하다.
DataItem.js를 React.memo로 감쌀 것이다.
DataItem.js
import React from "react";
const DataItem = React.memo(({ name, seq }) => {
return (
<div>
{name} and {seq}
</div>
);
});
export default DataItem;
이렇게만 해주면 DataItem component를 다시 재사용함으로서 rendering이 덜 일어남을 확인할 수 있다.
2. useCallback 사용하기
useCallback은 memoization된 콜백을 반환하는 hook이다.
즉, 이것도 useMemo와 마찬가지로 성능 최적화를 위해 사용되는 hook 중 하나이다.
이를 위해 좋은 예시가 있어서 내 연습장에 추가했다.
예시를 보기 전에 잠깐! 다시 한 번 더 뜻을 되새김질 해보자.
callback이 무엇인가? 특정 함수들을 후의 처리로 넘기는 것이다. 어떤 작업이 벌어진 뒤에, 함수를 부른다는 것이다.
너를 다시 나중에 부를게! 콜백!
그러면 useCallback은? react에서 callback기능을 사용할 수 있게 지원하는 것일 뿐이다.
App.js - 구조만 정리
import React from "react";
import "./App.css";
import Clock from "./Clock";
import Count from "./Count";
import Header from "./Header";
export const UserContext = React.createContext();
function App() {
let state = {
result: "result",
text: "text",
name: "thelovemg",
};
return (
<UserContext.Provider value={state}>
<div className="App">
<Header />
<Clock />
<Count />
<br />
</div>
</UserContext.Provider>
);
}
export default App;
Header.js - Light component 추가
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import { UserContext } from "./App";
import DataList from "./DataList";
import Light from "./Light";
const Header = () => {
const [datas, setDatas] = useState([
{
name: "test1",
seq: 123,
},
{
name: "test2",
seq: 122,
},
{
name: "test4",
seq: 124,
},
]);
const { text, name } = useContext(UserContext);
const [resultStr, setResultStr] = useState("");
const addTagContent = useRef("");
useEffect(() => {
addTagContent.current = resultStr;
}, [resultStr]);
const [masterOn, setMasterOn] = useState(false);
const [kitchenOn, setKitchenOn] = useState(false);
const [bathOn, setBathOn] = useState(false);
const toggleMaster = useCallback(() => {
setMasterOn(!masterOn);
}, [masterOn]);
const toggleKitchen = useCallback(() => {
setKitchenOn(!kitchenOn);
}, [kitchenOn]);
const toggleBath = useCallback(() => {
setBathOn(!bathOn);
}, [bathOn]);
return (
<div>
<div>
<h1>{resultStr}</h1>
<button
onClick={() => {
setResultStr((c) => c + "test");
}}
>
add string to first tag... :
</button>
<DataList datas={datas} />
<br />
<div>
<Light room="침실" on={masterOn} toggle={toggleMaster}></Light>
<Light room="주방" on={kitchenOn} toggle={toggleKitchen}></Light>
<Light room="욕실" on={bathOn} toggle={toggleBath}></Light>
</div>
</div>
<br />
header : {text} & {name}
</div>
);
};
export default Header;
Light.js
import React from "react";
function Light({ room, on, toggle }) {
console.log({ room, on });
return (
<div>
<button onClick={toggle}>
{room}
{on ? "💡" : "⬛"}
</button>
</div>
);
}
export default React.memo(Light);
그러면 버튼 클릭시 해당되는 Light component만 하이라이팅 되며 console도 하나만 나오는 것을 확인할 수 있다.
내가 직접 만들어서 하고싶은 욕심이 있었지만 이미 좋은 예시를 보고 말았으니 더이상 떠오르지가 않았다...ㅠㅠ
좋은 글 작성해주신 선배님 감사합니다...
'programming language > react' 카테고리의 다른 글
[React] React Router 파해치기 (0) | 2022.06.12 |
---|---|
[React] useReducer / React Router 사용하기 (0) | 2022.06.12 |
[React] React Hook - useContext, useRef, useMemo 적용하기 (0) | 2022.06.10 |
[React] Props와 State 이해하기 / Hook(useState, useEffect) 적용 (0) | 2022.06.07 |
[React] 리액트(React)란 무엇인가? / create-react-app 사용하기 (0) | 2022.06.07 |