함수가 렌더링 된다는 것은 누구가 그 함수를 호출하여 실행되는 것
함수가 실행될 때마다 내부에 선언되어 있던 표현식들도 매번 다시 계산된다.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
첫번째 인자로는 함수, 두번째 인자로는 dependency를 전달한다.
useMemo는 의존성이 변경되었을 때에만 메모이제이션된 값을 반환한다.
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
useCallback은 메모이제이션 된 콜백을 반환한다.
함수가 다시 선언되고 실행되는 것을 방지한다.
함수형 컴포넌트 안에서, 함수가 실행 될 때마다 내부에 선언되어 있는 표현식들이 매번 다시 계산되기 때문에, 함수에서 밖으로 뺄 수 있는 것들은 미리미리 밖으로 빼 놓아야 한다.
컴포넌트 자체를 메모하는 방법
const MyComponent = React.memo(function MyComponent(props) {
/* props를 사용하여 렌더링 */
});
React.memo는 컴포넌트 자체를 memo 하는 것으로, props의 변화에 의해서만 동작한다.
동일한 props로 동일한 결과를 낸다면, 메모이제이션 된 마지막 렌더링 결과를 사용한다.
따라서, React.memo는 props 변화에만 영향을 준다. React.memo로 감싸진 함수 컴포넌트 구현에 useState, useReducer 또는 useContext 훅을 사용한다면, 여전히 state나 context가 변할 때 다시 렌더링된다.
대부분 React 앱들은 Webpack, Rollup 또는 Browserify 같은 툴을 사용하여 여러 파일을 하나로 병합한 “번들 된” 파일을 웹 페이지에 포함하여 한 번에 전체 앱을 로드 할 수 있습니다.
따라서 번들된 파일들이 크게되면, 최초에 로딩하는데 시간이 굉장히 많이 걸린다.
해결방법으로 코드분할을 해서 "지연 로딩"을 하도록 도와주는 것이다.
Before
import { add } from './math';
console.log(add(16, 26));
After
import("./math").then(math => {
console.log(math.add(16, 26));
});
React.lazy 함수를 사용하면 동적 import를 사용해서 컴포넌트를 렌더링 할 수 있습니다.
Before
import OtherComponent from './OtherComponent';
After
const OtherComponent = React.lazy(() => import('./OtherComponent'));
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
위와 같이 suspense로 감싸주며,렌더링 되는 동안 fallback 안의 컴포넌트가 보여지게 된다.
코드분할은 대부분 라우트 장소에 실시하여, 페이지 전환에 렌더링하게 되어, 다른 요소와 상호작용 하지 않도록 한다.
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
</Router>
);