티스토리 뷰
공부일지(TIL)/JS Framework + Library
[React] re-render가 일어나는 경우와 불필요한 리렌더를 줄이는 법
Alledy 2023. 3. 18. 00:19리렌더: 이미 스크린에 그려진 컴포넌트가 다시 렌더링되는 것
리렌더링은 언제 일어나는가?
- 컴포넌트의 state이 변했을 때, 해당 컴포넌트가 리렌더링됨
- 부모가 리렌더링됐을 때, 자식 컴포넌트도 리렌더링됨 (엣지 케이스가 있으나 일반적으로 그러함)
- Context Provider 값이 바뀌었을 때 그 컨텍스트를 사용하는 모든 컴포넌트가 리렌더링됨.
- 훅 내부에서 state 변동이 있거나 context 값 변동이 있으면 그 훅을 소비하는 컴포넌트가 리렌더링 됨.
function Parent() {
const [state, setState] = useState(); // state이 변하면 Parent 컴포넌트 리렌더링됨
// Parent 컴포넌트가 리렌더링되면 Child 컴포넌트도 리렌더링됨
return <Child />
}
반대로 리렌더링을 유발하지 않는 것은?
- props 변동 (메모이제이션된 컴포넌트는 예외임)
- props가 변동하기 위해서는 부모 컴포넌트의 값이 업데이트되어야 하고 이것이 리렌더링을 유발하고 부모 컴포넌트가 리렌더링되면 자식 컴포넌트도 리렌더링되지만 이것은 props 변동이 원인인 것이 아님.
- 값의 업데이트가 일어나면서 리렌더링과 props변동 둘 다 일어나는 것뿐.
컴포넌트 합성으로 리렌더링 방지하기
안티패턴
- 컴포넌트 안에서 새로운 컴포넌트를 생성해서 리턴하기
위 케이스는 Component가 리렌더링 될 때마다 SlowComponent가 re-mount되기 때문에 단순한 리렌더링보다 더 느리다. 하지만 굳이 이렇게 코딩하는 경우는 크게 없을 듯.function Component() { // 컴포넌트 안에서 컴포넌트 생성 후 리턴 function SlowComponent() { return <Something /> } return <SlowComponent /> }
state를 밑으로 내리기
- state가 변동하면 해당 컴포넌트가 리렌더링되고 모든 Child가 또 리렌더링되기 때문에, state를 국한지을 수 있다면 가급적 부모보다는 낮은 위계에 분리시키는 것이 불필요한 리렌더링을 줄일 수 있다.
// 이 경우 state가 변경되면 children인 VerySlowComponent도 리렌더링된다.
function Component {
const [open, setOpen] = useState(false);
return (
<Container>
<Button onClick={() => {setOpen(true)}} />
{isOpen && <ModalDialog />}
<VerySlowComponent />
</Container>
)
}
// children의 리렌더링은 parent에게 영향을 주지 않으므로, 이 케이스에서는 VerySlowComponent가 영향받지 않는다.
function ModalOpenButton() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => {setOpen(true)}} />
{isOpen && <ModalDialog />}
</>
)
}
function Component {
return (
<Container>
<ModalOpenButton />
<VerySlowComponent />
</Container>
)
}
Children as prop
- 이것도 state를 내리는 기법과 비슷하다. state를 보다 작은 부분에 캡슐화해서 분리하는 방법이기 때문이다.
- 그리고 props가 리렌더링이랑 관련없다는 사실도 기억해야 한다.
function Component() {
const [state, setState] = useState()
return (
<div onScroll={(e) => setState(e)}>
<VerySlowComponent />
</div>
)
}
function Scroll({ children }) {
const [state, setState] = useState()
return (
<div onScroll={(e) => setState(e)}>
{children}
</div>
)
}
// 리렌더링은 Scroll에서만 일어난다. 이 리렌더링은 props.children인 VerySlowComponent에는 영향을 주지 않는다.
function Component() {
return (
<Scroll>
<VerySlowComponent />
</Scroll>
)
}
Component as props
- 위에와 아주 비슷한 패턴이다. 다만 children이 아닌 props일 뿐.
function Component() {
const [state, setState] = useState()
return (
<div onScroll={(e) => setState(e)}>
<VerySlowComponentOne />
<Something />
<VerySlowComponentTwo />
</div>
)
}
function Scroll({ left, right }) {
const [state, setState] = useState()
return (
<div onScroll={(e) => setState(e)}>
{left}
<Something />
{right}
</div>
)
}
// 리렌더링은 Scroll에서만 일어난다. 이 리렌더링은 props.left, props.right인 VerySlowComponent들에는 영향을 주지 않는다.
function Component() {
return (
<Scroll
left={<VerySlowComponentOne />}
right={<VerySlowComponentTwo />}
/>
)
}
- props가 리렌더링에 영향을 주는 예외 케이스는 메모이제이션된 컴포넌트일 경우다. 이 케이스는 다음 편에 마저 작성할 예정.
Ref
'공부일지(TIL) > JS Framework + Library' 카테고리의 다른 글
[React Navigation] Nested Navigator (0) | 2023.05.17 |
---|---|
[React Native] ScrollView keyboardShouldPersistTaps (0) | 2023.04.12 |
[React Query] Tracked Query (0) | 2023.03.16 |
[React] usePrevious hook (0) | 2023.02.13 |
[React Query] active하고 stale한 쿼리의 refetch (0) | 2023.01.11 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 자바
- package.json
- Prefix Sums
- this
- Java
- til
- 제네릭스
- 알고리즘
- SQL
- JavaScript
- CSS
- getter
- 인스턴스
- 포인터 변수
- Data Structure
- rxjs
- useEffect
- 개발 공부
- react
- linkedlist
- GIT
- youtube data api
- Conflict
- Redux
- jQuery
- 리덕스
- Session
- 깃
- c언어
- oracle
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함