리렌더링이 발생하는 상황
- 최초 렌더링이 끝난 이후, 컴포넌트의 State가 바뀌면 해당 컴포넌트와 그의 자식 컴포넌트는 리렌더링된다.
리렌더링 사이클

- Rerendering → DOM update → useLayoutEffect → useEffect
리렌더링 확인 방법
- useEffect에 의존성 배열을 넣지 않으면 컴포넌트가 리렌더링될 때마다 실행된다.
특정 state의 변화 확인 방법
- 리렌더링되더라도 우선 Virtual DOM을 생성하고 이전 DOM과 비교하는 과정을 거쳐 변화된 부분만 바꿔주기 때문에 컴포넌트의 변화가 없더라도 리렌더링이 일어날 수 있다.
- state의 변화가 있는지 확인하기 위하여 useEffect의 의존성 배열에 관찰하려는 props나 state를 넣어주면 의존성 배열에 넣어준 값이 바뀔 때마다 실행된다.
렌더링 최적화 방법
- 리액트 컴포넌트가 렌더링 결과물을 지난번과 정확히 동일한 참조를 반환한다면, 리액트는 해당 하위 컴포넌트를 렌더링하는 것을 건너 뛴다.
import React, { ReactElement, useEffect, useState } from 'react';
const Parent = ({ children }: { children: ReactElement }) => {
const [counter, setCounter] = useState(0);
useEffect(() => {
console.log('parent');
});
return (
<div>
<button onClick={() => setCounter((counter) => counter + 1)}>Count: {counter}</button>
{children}
</div>
);
};
const Child = () => {
useEffect(() => {
console.log('child');
});
return <div>Hello</div>;
};
function App() {
return (
<Parent>
<Child />
</Parent>
);
}
export default App;
import React, { useEffect, useMemo, useState } from 'react';
const Child = () => {
useEffect(()=>{
console.log('child')
})
return (
<div>Hello</div>
)
}
function App() {
const [counter1, setCounter1] = useState(0)
const [counter2, setCounter2] = useState(0)
useEffect(()=>{
console.log('parent')
})
const memoizedElement = useMemo(()=>{
return <Child/>
// eslint-disable-next-line react-hooks/exhaustive-deps
},[counter1])
return (
<div>
<button onClick={()=> setCounter1(counter => counter+1)}>Counter 1: {counter1}</button>
<button onClick={()=> setCounter2(counter => counter+1)}>Counter 2: {counter2}</button>
{memoizedElement}
</div>
);
}
export default App;