본문 바로가기

리액트 공식 문서 읽기

19화: Preserving and Resetting State

이 글은 단순히 리액트 공식 문서를 읽고 베꼈을 뿐이다!! 학습 목적이라면 공식 문서를 보는 걸 추천한다.

 

참새들. Unsplash 에 Manuel Torres Garcia 님이 올림.

공식 문서

https://react.dev/learn/preserving-and-resetting-state

 

Preserving and Resetting State – React

The library for web and native user interfaces

react.dev

UI 트리

  • 리액트: JSX를 이용해 UI 트리를 만듦
  • 리액트 DOM: 브라우저 DOM과 UI 트리가 일치하도록 만듦
  • 리액트 네이티브: UI 트리를 모바일 플랫폼에 적합한 요소들로 바꿈

상태는 트리에서의 위치에 묶여 있다

  • 상태가 '컴포넌트' 안에 있다고 생각할 수 있지만 그건 아님
  • 상태는 '리액트' 안에 있음
  • 리액트는 자신이 갖고 있는 각 상태들을 컴포넌트의 UI 트리에서의 위치와 연관지어서 기억함
  • 똑같은 컴포넌트를 같은 div 안에 두 개 렌더링하면 각 컴포넌트는 UI 트리에서의 위치가 달라서 독립된 상태를 가짐
  • 같은 컴포넌트를 같은 위치에 리렌더링한다면 리액트는 상태를 계속 기억함
  • 리액트가 컴포넌트를 제거할 때는 기억하고 있던 그 컴포넌트의 상태를 버림

같은 위치의 같은 컴포넌트면 상태를 기억한다

  • 어떤 컴포넌트의 상태'만' 바뀌었을 때 자기 자신의 상태가 초기화되지 않는 이유임
  • 상태가 바뀌어서 리렌더링이 일어나지만, 같은 위치의 같은 컴포넌트이므로 바뀐 상태를 유지할 수 있음
  • JSX 마크업이 아니라 UI 트리의 위치가 같아야 함: 렌더링 도중에 return문으로 다른 JSX를 보냈어도 UI 트리에서 보기에 같은 위치의 같은 컴포넌트면 같은 거임

같은 위치의 다른 컴포넌트면 상태를 초기화한다

  • A 컴포넌트가 있던 자리에 B 컴포넌트를 놓으면 A가 제거되면서 A의 상태 역시 없어짐
  • 부모 컴포넌트의 종류가 바뀌면 부모 컴포넌트가 제거될 때 그 밑의 자식들까지 같이 없어짐 -> 자식은 같은 컴포넌트더라도 상태를 잃어버림
  • 컴포넌트의 위치가 '트리의 뿌리부터 무슨무슨 방향으로 가서 몇 번째요' 이게 아니라 본인 부모의 종류까지 전부 다 맞아야 상태를 유지할 수 있는 거
  • 이래서 컴포넌트 정의를 중첩하지 말라는 거임
    • A 컴포넌트 안에 'B 컴포넌트를 만드는 함수'가 있다고 치자
    • A가 리렌더링될때 B 컴포넌트를 만드는 함수는 재정의됨 -> 리액트는 기존의 'B 컴포넌트를 만드는 함수'와 재정의된 'B 컴포넌트를 만드는 함수'를 다르게 평가함

같은 위치의 같은 컴포넌트인데 상태 초기화하기

  1. 컴포넌트를 나누고 서로 다른 위치에 렌더링하기
    • 특정 조건일 때 하나의 컴포넌트만 렌더링하고 나머지는 null 등으로 처리
    • 눈으로 보기에는 같은 위치의 같은 컴포넌트지만 리액트는 null일 때 UI 트리에서 해당 컴포넌트를 제거하므로 상태를 잃어버림
  2. key를 이용하기
    • key는 리액트가 컴포넌트끼리 구별하는 데 사용
    • 기본적으로 리액트는 key가 없을 때는 부모의 몇 번째 자식인지 그 순서를 이용함
    • 하지만 key가 있다면 단순히 '몇 번째' 자식인지가 아니라 그 자식의 '이름이 뭔지'를 이용하게끔 함
    • 참고) key는 어플리케이션 전체에서 고유할 필요 없음. '같은 부모'를 갖는 형제자매들끼리만 서로 고유하면 됨

제거된 컴포넌트의 상태를 기억하기

상태 초기화하기의 핵심은 기존 컴포넌트를 UI 트리에서 제거하는 거라 기존의 상태를 무조건 잃어버린다. 하지만 카카오톡, 슬랙, 디스코드 등을 생각해 보면 어떤 채팅방에서 글을 쓰다 말고 다른 채팅방으로 갔다 와도 쓰던 내용이 유지된다. 이런 구현은 어떻게 해야 할까?

  • 모든 채팅방을 렌더링한 후 css를 이용해 나머지 채팅방들을 전부 숨김: 채팅방이 많아질수록 성능 저하
  • 상태 끌어올리기를 통해 부모가 기억하게 시킴: 가장 일반적인 해결책
  • 외부 저장소 이용: 로컬스토리지 등