[React] Preserving and Resetting State

2023. 10. 16. 09:31·프로젝트/정글 FE 스터디

state 보존 및 재설정

state는 컴포넌트 간에 격리된다. React는 UI 트리에서 어떤 컴포넌트가 어떤 state에 속하는지를 추적한다. React는 state를 언제 보존하고 언제 초기화할지를 제어할 수 있다.

학습 내용

  • React가 컴포넌트 구조를 “보는” 방법
  • React가 state를 유지하거나 재설정하도록 선택할 때
  • React가 컴포넌트의 state를 재설정하도록 강제하는 방법
  • key와 type이 state 보존 여부에 영향을 미치는 방법

UI 트리

  • 브라우저는 UI를 모델링하기 위해 "여러 트리 구조"를 사용한다.
  • DOM은 HTML element
  • CSSOM은 CSS
  • Accessibility 트리도 있다!

=> 이처럼, React도 트리 구조를 사용하여 사용자의 UI를 관리하고 모델링한다!

  • React이 JSX(또는 TSX)로부터 UI 트리를 만든다. 그런 다음 React DOM은 해당 UI 트리와 일치하도록 브라우저 DOM을 업데이트한다.

state는 트리의 한 위치에 묶인다.

  • 컴포넌트에 state를 부여할 때
  • 컴포넌트 내부에 state가 존재한다고 생각할 수도 있다.
  • 그러나, 실제로 state는 React 내부에서 유지된다.
  • React는 UI 트리에서 컴포넌트의 위치에 따라 보유하고 있는 각 state를 올바른 컴포넌트와 연결한다.

동일한 위치의 동일한 컴포넌트는 state를 유지한다.

  • React는 컴포넌트가 UI 트리의 해당 위치에서 렌더링되는 동안 컴포넌트의 state를 유지한다.
  • 즉, 컴포넌트가 제거되거나 같은 위치에 다른 컴포넌트가 렌더링되면 React는 해당 컴포넌트의 state를 삭제한다.
    <div>{isFancy ? (
        <Counter isFancy={true} /> 
      ) : (
        <Counter isFancy={false} /> 
      )}</div>
  • isFancy가 true이든 false이든, 가 렌더링되는 것은 동일하기 때문에 Counter의 state는 재설정되지 않는다!
  • UI 트리에서의 위치가 같기 때문에 React의 관점에서는 같은 컴포넌트이다.

동일한 위치의 다른 컴포넌트는 state를 초기화한다.

<div>
      {isPaused ? (
        <p>See you later!</p> 
      ) : (
        <Counter /> 
      )}
      </div>
  • UI 트리 상에서 같은 위치에 다른 컴포넌트가 전환되므로, React는 Counter를 제거하고 그 state를 소멸시킨다.
  • 또한, 같은 위치에 다른 컴포넌트를 렌더링하면 전체 하위 트리의 state가 재설정된다.
<div>
      {isFancy ? (
        <div>
          <Counter isFancy={true} /> 
        </div>
      ) : (
        <section>
          <Counter isFancy={false} />
        </section>
      )}</div>
  • 위 컴포넌트가 서로 전환되면 state가 재설정된다.
  • 가 렌더링되더라도 div의 첫 번째 자식이 div에서 section으로 변경되었기 때문에, 자식 div가 DOM에서 제거되면 하위 전체 트리도 함께 제거된다.

컴포넌트를 중첩하지 말자.

import { useState } from 'react';

export default function MyComponent() {
  const [counter, setCounter] = useState(0);

  function MyTextField() {
    const [text, setText] = useState('');

    return (
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
    );
  }

  return (
    <>
      <MyTextField />
      <button onClick={() => {
        setCounter(counter + 1)
      }}>Clicked {counter} times</button>
    </>
  );
}
  • 이 컴포넌트는 버튼을 입력할 때마다 state가 사라진다.
  • 이는 MyComponent를 렌더링할 때마다 다른 MyTextField 함수가 생성되기 때문이다.
  • 이 문제를 방지하려면 항상 컴포넌트 함수를 최상위 수준에서 선언해야 한다!

동일한 위치에서 state 재설정하기

  • 기본적으로 React는 컴포넌트가 같은 위치에 있는 동안 state를 보존한다.
  • 그러나 가끔 state를 의도적으로 리셋하고 싶을 때가 있다.
  • 컴포넌트를 같은 위치에서 전환할 때, state를 재설정하는 방법은 두 가지가 있다!
  1. 컴포넌트를 다른 위치에서 렌더링하기
{isPlayerA &&
        <Counter person="Taylor" />
      }
      {!isPlayerA &&
        <Counter person="Sarah" />
      }
  • 두 카운터를 독립적으로 만들기 위해서는 두 개의 다른 위치에 렌더링하면 된다.
  • 각 카운터의 state는 DOM에서 제거될 때마다 소멸된다.
  • 이 솔루션은 같은 위치에 몇 개의 독립적인 컴포넌트만 렌더링할 때 편리하다.
  1. key로 state 재설정하기
  • 반복문을 사용해서 목록을 렌더링할 때처럼 key를 사용하면 된다.
  • 컴포넌트마다 다른 key를 지정하면 React에게 다른 컴포넌트 임을 알릴 수 있다.
  • key를 지정하면 React가 부모 내순서가 아닌 key 자체를 위치의 일부로 사용하도록 지시한다.
  • 따라서 JSX에서 같은 위치에 렌더링하더라도 React의 관점에서 보면 서로 다른 카운터이다.
  • 단, key는 전역으로 고유하지는 않다! key는 부모 내에서의 위치만 지정한다.

제거된 컴포넌트에 대한 state 보존

  • 제거된 컴포넌트의 state를 보존했다가 복구하고 싶을 때가 있다.
  • 다음의 방법을 사용해보자.
  1. 현재 컴포넌트만 "렌더링"하는 것이 아니라, 모든 컴포넌트를 렌더링하되 다른 모든 컴포넌트를 css로 숨길 수 있다. 컴포넌트는 트리에서 제거되지 않으므로 로컬 state가 유지된다! 간단하지만 숨겨진 트리가 크고 많은 DOM 노드를 포함한 경우 속도가 매우 느려질 수 있다.
  2. 부모 컴포넌트에서 각 자식의 state를 끌어올려서 보관할 수 있다. 가장 일반적인 솔루션이다.
  3. React state 외에 다른 소스를 사용할 수 있다. localStorage 에 값을 쓰고 읽어서 state를 초기화할 수 있다!

Recap

  • React는 동일한 컴포넌트가 동일한 위치에서 렌더링되는 한 state를 유지한다.
  • state는 JSX 태그에 보관되지 않습니다. JSX를 넣은 트리 위치와 연관되어 있다.
  • 하위 트리에 다른 key를 지정하여 강제로 state를 재설정할 수 있다.
  • 컴포넌트 정의를 중첩하지 마세요. 실수로 state가 초기화될 수 있다.

'프로젝트 > 정글 FE 스터디' 카테고리의 다른 글

[React] Passing Data Deeply with Context  (1) 2023.10.16
[FE] Deep Dive - 44장 REST API  (0) 2023.10.16
[React] Choosing the State Structure  (0) 2023.10.16
[React] State as a Snapshot  (0) 2023.09.19
[React] Render and Commit  (0) 2023.09.18
'프로젝트/정글 FE 스터디' 카테고리의 다른 글
  • [React] Passing Data Deeply with Context
  • [FE] Deep Dive - 44장 REST API
  • [React] Choosing the State Structure
  • [React] State as a Snapshot
KimCookieYa
KimCookieYa
무엇이 나를 살아있게 만드는가
  • KimCookieYa
    쿠키의 주저리
    KimCookieYa
  • 전체
    오늘
    어제
    • 분류 전체보기 (573) N
      • 혼잣말 (87)
      • TIL (2)
      • 커리어 (24)
        • Sendy (21)
        • 외부활동 기록 (2)
      • 프로젝트 (186)
        • 티스토리 API (5)
        • 코드프레소 체험단 (89)
        • Web3 (3)
        • Pint OS (16)
        • 나만무 (14)
        • 대회 (6)
        • 정글 FE 스터디 (16)
        • MailBadara (12)
        • github.io (1)
        • 인공지능 동아리, AID (5)
        • 졸업과제 (18)
        • OSSCA 2024 (1)
      • 크래프톤 정글 2기 (80)
      • IT (168) N
        • 코딩 (4)
        • CS (18)
        • 에러 (5)
        • 블록체인 (23)
        • Front-End (39) N
        • 알고리즘&자료구조 정리 (3)
        • 코딩테스트 (3)
        • BOJ 문제정리 (41)
        • WILT (12)
        • ML-Agents (4)
        • 강화학습 (1)
        • Android (0)
        • LLM (2)
      • 전공 (1)
        • 머신러닝 (1)
      • 자기계발 (20)
        • 빡공단X베어유 (2)
        • 독서 (15)
  • 블로그 메뉴

    • 홈
    • 방명록
    • Github
    • Velog
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    numpy
    파이썬
    나만무
    docker
    NEAR Protocol
    사이드프로젝트
    Pint OS
    RNN
    pintos
    JavaScript
    딥러닝
    MailBadara
    자바스크립트
    글리치해커톤
    Flutter
    OS
    머신러닝
    크래프톤정글
    블록체인
    핀토스
    프로그래머스
    알고리즘
    해커톤
    니어프로토콜
    위상정렬
    리액트
    부산대
    졸업과제
    코드프레소
    react
  • hELLO· Designed By정상우.v4.10.3
KimCookieYa
[React] Preserving and Resetting State
상단으로

티스토리툴바