v19.2Latest

상태 보존 및 재설정

상태는 컴포넌트 간에 격리됩니다. React는 UI 트리에서의 위치를 기준으로 어떤 상태가 어떤 컴포넌트에 속하는지 추적합니다. 다시 렌더링할 때 상태를 언제 보존하고 언제 재설정할지 제어할 수 있습니다.

배울 내용
  • React가 상태를 보존하거나 재설정하는 경우
  • React가 컴포넌트의 상태를 재설정하도록 강제하는 방법
  • 키와 타입이 상태 보존에 미치는 영향

상태는 렌더 트리 내 위치에 연결됩니다

React는 UI의 컴포넌트 구조에 대한렌더 트리를 구축합니다.

컴포넌트에 상태를 부여하면 상태가 컴포넌트 "내부에" 존재한다고 생각할 수 있습니다. 하지만 상태는 실제로 React 내부에 보관됩니다. React는 보유한 각 상태 조각을 해당 컴포넌트가 렌더 트리에서 위치한 곳에 따라 올바른 컴포넌트와 연결합니다.

여기에는 하나의<Counter />JSX 태그만 있지만, 두 개의 다른 위치에서 렌더링됩니다:

트리로 표현하면 다음과 같습니다:

React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되고 두 개의 자식이 있습니다. 각 자식은 'Counter'로 표시되며 둘 다 값이 0인 'count'라는 상태 버블을 포함합니다.React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되고 두 개의 자식이 있습니다. 각 자식은 'Counter'로 표시되며 둘 다 값이 0인 'count'라는 상태 버블을 포함합니다.

React 트리

이는 트리에서 각각 고유한 위치에 렌더링되기 때문에 두 개의 별도 카운터입니다.React를 사용할 때 일반적으로 이러한 위치에 대해 생각할 필요는 없지만, 작동 방식을 이해하는 데 유용할 수 있습니다.

React에서 화면의 각 컴포넌트는 완전히 격리된 상태를 가집니다. 예를 들어, 두 개의Counter컴포넌트를 나란히 렌더링하면 각각 고유하고 독립적인scorehover상태를 갖게 됩니다.

두 카운터를 모두 클릭해 보면 서로 영향을 미치지 않음을 확인할 수 있습니다:

보시다시피, 한 카운터가 업데이트되면 해당 컴포넌트의 상태만 업데이트됩니다:

React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되고 두 개의 자식이 있습니다. 왼쪽 자식은 'Counter'로 표시되며 값이 0인 'count'라는 상태 버블을 포함합니다. 오른쪽 자식은 'Counter'로 표시되며 값이 1인 'count'라는 상태 버블을 포함합니다. 오른쪽 자식의 상태 버블은 값이 업데이트되었음을 나타내기 위해 노란색으로 강조 표시됩니다.React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되고 두 개의 자식이 있습니다. 왼쪽 자식은 'Counter'로 표시되며 값이 0인 'count'라는 상태 버블을 포함합니다. 오른쪽 자식은 'Counter'로 표시되며 값이 1인 'count'라는 상태 버블을 포함합니다. 오른쪽 자식의 상태 버블은 값이 업데이트되었음을 나타내기 위해 노란색으로 강조 표시됩니다.

상태 업데이트

React는 트리에서 동일한 위치에 동일한 컴포넌트를 렌더링하는 한 상태를 유지합니다. 이를 확인하려면 두 카운터를 모두 증가시킨 다음, "두 번째 카운터 렌더링" 체크박스를 선택 해제하여 두 번째 컴포넌트를 제거하고, 다시 선택하여 추가하세요:

두 번째 카운터 렌더링을 중지하는 순간 해당 상태가 완전히 사라지는 것을 확인하세요. 이는 React가 컴포넌트를 제거할 때 해당 상태를 파괴하기 때문입니다.

React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되고 두 개의 자식이 있습니다. 왼쪽 자식은 'Counter'로 표시되며 값이 0인 'count'라는 상태 버블을 포함합니다. 오른쪽 자식은 없으며, 그 자리에 트리에서 삭제되는 컴포넌트를 강조하는 노란색 '펑' 이미지가 있습니다.React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되어 있으며 두 개의 자식이 있습니다. 왼쪽 자식은 'Counter'로 표시되어 있고 값이 0인 'count'라는 상태 버블을 포함하고 있습니다. 오른쪽 자식은 없으며, 그 자리에 트리에서 삭제되는 컴포넌트를 강조하는 노란색 '풍' 이미지가 있습니다.

컴포넌트 삭제

“두 번째 카운터 렌더링”을 선택하면 두 번째Counter와 그 상태가 처음부터 초기화되고(score = 0) DOM에 추가됩니다.

React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되어 있으며 두 개의 자식이 있습니다. 왼쪽 자식은 'Counter'로 표시되어 있고 값이 0인 'count'라는 상태 버블을 포함하고 있습니다. 오른쪽 자식은 'Counter'로 표시되어 있고 값이 0인 'count'라는 상태 버블을 포함하고 있습니다. 전체 오른쪽 자식 노드는 트리에 방금 추가되었음을 나타내는 노란색으로 강조 표시되어 있습니다.React 컴포넌트 트리 다이어그램. 루트 노드는 'div'로 표시되어 있으며 두 개의 자식이 있습니다. 왼쪽 자식은 'Counter'로 표시되어 있고 값이 0인 'count'라는 상태 버블을 포함하고 있습니다. 오른쪽 자식은 'Counter'로 표시되어 있고 값이 0인 'count'라는 상태 버블을 포함하고 있습니다. 전체 오른쪽 자식 노드는 트리에 방금 추가되었음을 나타내는 노란색으로 강조 표시되어 있습니다.

컴포넌트 추가

React는 컴포넌트가 UI 트리에서 자신의 위치에 렌더링되는 동안 그 상태를 보존합니다.컴포넌트가 제거되거나 같은 위치에 다른 컴포넌트가 렌더링되면 React는 그 상태를 버립니다.

같은 위치의 같은 컴포넌트는 상태를 보존합니다

이 예제에는 두 개의 다른<Counter />태그가 있습니다:

체크박스를 선택하거나 선택 해제해도 카운터 상태는 초기화되지 않습니다.isFancytrue이든false이든, 항상 루트App컴포넌트에서 반환된div의 첫 번째 자식으로<Counter />가 있습니다:

두 개의 섹션을 화살표로 구분한 다이어그램. 각 섹션에는 'App'으로 표시된 부모 컴포넌트가 포함된 컴포넌트 레이아웃이 있으며, isFancy라는 상태 버블을 포함하고 있습니다. 이 컴포넌트에는 'div'로 표시된 하나의 자식이 있으며, 이는 전달되는 유일한 자식에게 전달되는 isFancy(보라색으로 강조 표시됨)를 포함하는 prop 버블로 이어집니다. 마지막 자식은 'Counter'로 표시되어 있으며 두 다이어그램 모두에서 값이 3인 'count'라는 레이블의 상태 버블을 포함하고 있습니다. 다이어그램의 왼쪽 섹션에서는 아무것도 강조 표시되지 않았으며 isFancy 부모 상태 값은 false입니다. 다이어그램의 오른쪽 섹션에서는 isFancy 부모 상태 값이 true로 변경되었으며 노란색으로 강조 표시되어 있고, 아래의 props 버블도 isFancy 값이 true로 변경되어 노란색으로 강조 표시되어 있습니다.두 개의 섹션을 화살표로 구분한 다이어그램. 각 섹션에는 'App'으로 표시된 부모 컴포넌트가 포함된 컴포넌트 레이아웃이 있으며, isFancy라는 상태 버블을 포함하고 있습니다. 이 컴포넌트에는 'div'로 표시된 하나의 자식이 있으며, 이는 전달되는 유일한 자식에게 전달되는 isFancy(보라색으로 강조 표시됨)를 포함하는 prop 버블로 이어집니다. 마지막 자식은 'Counter'로 표시되어 있으며 두 다이어그램 모두에서 값이 3인 'count'라는 레이블의 상태 버블을 포함하고 있습니다. 다이어그램의 왼쪽 섹션에서는 아무것도 강조 표시되지 않았으며 isFancy 부모 상태 값은 false입니다. 다이어그램의 오른쪽 섹션에서는 isFancy 부모 상태 값이 true로 변경되었으며 노란색으로 강조 표시되어 있고, 아래의 props 버블도 isFancy 값이 true로 변경되어 노란색으로 강조 표시되어 있습니다.

Counter가 같은 위치에 있기 때문입니다

같은 위치의 같은 컴포넌트이므로, React의 관점에서는 같은 카운터입니다.

주의사항

기억하세요,React에게 중요한 것은 JSX 마크업이 아니라 UI 트리에서의 위치입니다!이 컴포넌트에는if문 안팎에 서로 다른<Counter />JSX 태그를 가진 두 개의return절이 있습니다:

체크박스를 선택하면 상태가 초기화될 것 같지만 그렇지 않습니다! 이는이 두 <Counter />태그가 같은 위치에 렌더링되기 때문입니다.React는 함수 내에서 조건을 어디에 배치했는지 알지 못합니다. React가 “보는” 것은 반환하는 트리뿐입니다.

두 경우 모두,App컴포넌트는 첫 번째 자식으로<Counter />를 가진<div>를 반환합니다. React에게 이 두 카운터는 같은 “주소”를 가집니다: 루트의 첫 번째 자식의 첫 번째 자식. 이것이 React가 이전 렌더와 다음 렌더 사이에서 이들을 매칭하는 방식이며, 논리 구조와는 관계없습니다.

같은 위치의 다른 컴포넌트는 상태를 초기화합니다

이 예제에서 체크박스를 선택하면<Counter><p>로 대체합니다:

여기서는 동일한 위치에서다른 컴포넌트 타입으로 전환합니다. 처음에는 <div>의 첫 번째 자식에Counter가 있었습니다. 하지만p로 교체하면 React는 UI 트리에서Counter를 제거하고 그 상태를 파괴합니다.

세 개의 섹션으로 구성된 다이어그램으로, 각 섹션 사이에 전환을 나타내는 화살표가 있습니다. 첫 번째 섹션에는 'div'로 레이블된 React 컴포넌트가 있으며, 값이 3인 'count' 상태 버블을 포함한 'Counter'라는 단일 자식이 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트가 이제 삭제되었으며, 이를 노란색 'proof' 이미지로 표시했습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'p'라는 새 자식이 있습니다.세 개의 섹션으로 구성된 다이어그램으로, 각 섹션 사이에 전환을 나타내는 화살표가 있습니다. 첫 번째 섹션에는 'div'로 레이블된 React 컴포넌트가 있으며, 값이 3인 'count' 상태 버블을 포함한 'Counter'라는 단일 자식이 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트가 이제 삭제되었으며, 이를 노란색 'proof' 이미지로 표시했습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'p'라는 새 자식이 있습니다.

Counterp로 변경되면Counter가 삭제되고p가 추가됩니다

세 개의 섹션으로 구성된 다이어그램으로, 각 섹션 사이에 전환을 나타내는 화살표가 있습니다. 첫 번째 섹션에는 'p'로 레이블된 React 컴포넌트가 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트가 이제 삭제되었으며, 이를 노란색 'proof' 이미지로 표시했습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'Counter'라는 새 자식이 있으며, 값이 0인 'count' 상태 버블을 포함하고 있습니다.세 개의 섹션으로 구성된 다이어그램으로, 각 섹션 사이에 전환을 나타내는 화살표가 있습니다. 첫 번째 섹션에는 'p'로 레이블된 React 컴포넌트가 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트가 이제 삭제되었으며, 이를 노란색 'proof' 이미지로 표시했습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'Counter'라는 새 자식이 있으며, 값이 0인 'count' 상태 버블을 포함하고 있습니다.

다시 전환할 때는p가 삭제되고Counter가 추가됩니다

또한,동일한 위치에 다른 컴포넌트를 렌더링하면 해당 하위 트리의 전체 상태가 재설정됩니다.이 동작을 확인하려면 카운터를 증가시킨 후 체크박스를 선택하세요:

체크박스를 클릭하면 카운터 상태가 재설정됩니다.Counter를 렌더링하더라도div의 첫 번째 자식이section에서div로 변경됩니다. 자식section이 DOM에서 제거되면 그 아래의 전체 트리(Counter와 그 상태를 포함)도 함께 파괴됩니다.

세 개의 섹션으로 구성된 다이어그램으로, 각 섹션 사이에 전환을 나타내는 화살표가 있습니다. 첫 번째 섹션에는 'div'로 레이블된 React 컴포넌트가 있으며, 단일 자식인 'section'이 있고, 그 자식으로 값이 3인 'count' 상태 버블을 포함한 'Counter'가 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트들이 이제 삭제되었으며, 이를 노란색 'proof' 이미지로 표시했습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'div'라는 새 자식이 있고, 그 자식으로 값이 0인 'count' 상태 버블을 포함한 'Counter'가 있으며, 모두 노란색으로 강조 표시되어 있습니다.세 개의 섹션으로 구성된 다이어그램으로, 각 섹션 사이에 전환을 나타내는 화살표가 있습니다. 첫 번째 섹션에는 'div'로 레이블된 React 컴포넌트가 있으며, 단일 자식인 'section'이 있고, 그 자식으로 값이 3인 'count' 상태 버블을 포함한 'Counter'가 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트들이 이제 삭제되었으며, 이를 노란색 'proof' 이미지로 표시했습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'div'라는 새 자식이 있고, 그 자식으로 값이 0인 'count' 상태 버블을 포함한 'Counter'가 있으며, 모두 노란색으로 강조 표시되어 있습니다.

sectiondiv로 변경되면section이 삭제되고 새로운div가 추가됩니다

세 개의 섹션으로 구성된 다이어그램이며, 각 섹션 사이를 전환하는 화살표가 있습니다. 첫 번째 섹션에는 'div'로 표시된 React 컴포넌트가 있으며, 그 자식으로 'div'로 표시된 단일 자식이 있고, 그 자식으로 'count' 상태 버블(값 0)을 포함하는 'Counter'로 표시된 단일 자식이 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트들이 삭제되었으며, 노란색 'proof' 이미지로 표시되어 있습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'section'으로 표시된 새 자식과, 'count' 상태 버블(값 0)을 포함하는 'Counter'로 표시된 새 자식이 있으며, 모두 노란색으로 강조 표시되어 있습니다.세 개의 섹션으로 구성된 다이어그램이며, 각 섹션 사이를 전환하는 화살표가 있습니다. 첫 번째 섹션에는 'div'로 표시된 React 컴포넌트가 있으며, 그 자식으로 'div'로 표시된 단일 자식이 있고, 그 자식으로 'count' 상태 버블(값 0)을 포함하는 'Counter'로 표시된 단일 자식이 있습니다. 중간 섹션에는 동일한 'div' 부모가 있지만, 자식 컴포넌트들이 삭제되었으며, 노란색 'proof' 이미지로 표시되어 있습니다. 세 번째 섹션에는 다시 동일한 'div' 부모가 있으며, 이제 노란색으로 강조 표시된 'section'으로 표시된 새 자식과, 'count' 상태 버블(값 0)을 포함하는 'Counter'로 표시된 새 자식이 있으며, 모두 노란색으로 강조 표시되어 있습니다.

다시 전환할 때,div가 삭제되고 새로운section이 추가됩니다.

경험적으로,리렌더링 사이에 상태를 유지하려면, 트리 구조가 한 렌더링에서 다음 렌더링으로 "일치"해야 합니다.구조가 다르면, React가 트리에서 컴포넌트를 제거할 때 상태를 파괴하기 때문에 상태가 파괴됩니다.

주의사항

이것이 컴포넌트 함수 정의를 중첩해서는 안 되는 이유입니다.

여기서MyTextField 컴포넌트 함수는 내부에MyComponent정의되어 있습니다:

버튼을 클릭할 때마다 입력 상태가 사라집니다! 이는다른MyTextField 함수가 MyComponent의 매 렌더링마다 생성되기 때문입니다. 동일한 위치에다른컴포넌트를 렌더링하고 있으므로 React는 아래의 모든 상태를 초기화합니다. 이는 버그와 성능 문제로 이어집니다. 이 문제를 피하려면,항상 컴포넌트 함수를 최상위 레벨에서 선언하고, 그 정의를 중첩하지 마세요.

동일한 위치에서 상태 초기화하기

기본적으로 React는 컴포넌트가 동일한 위치에 머무는 동안 그 상태를 보존합니다. 일반적으로 이것은 정확히 원하는 것이므로 기본 동작으로 합리적입니다. 하지만 때로는 컴포넌트의 상태를 초기화하고 싶을 수 있습니다. 각 턴마다 두 플레이어의 점수를 추적할 수 있는 이 앱을 고려해 보세요:

현재 플레이어를 변경하면 점수가 유지됩니다. 두 개의Counter가 동일한 위치에 나타나므로 React는 이를동일한Counter로 보고,personprop이 변경된 것으로 봅니다.

하지만 개념적으로, 이 앱에서 그들은 두 개의 별도 카운터여야 합니다. UI에서 동일한 위치에 나타날 수 있지만, 하나는 Taylor의 카운터이고 다른 하나는 Sarah의 카운터입니다.

그들 사이를 전환할 때 상태를 초기화하는 두 가지 방법이 있습니다:

  1. 컴포넌트를 다른 위치에 렌더링하기
  2. 각 컴포넌트에 key를 사용하여 명시적 식별자 부여하기

옵션 1: 컴포넌트를 다른 위치에 렌더링하기

이 두 Counter가 독립적이기를 원한다면, 두 개의 다른 위치에 렌더링할 수 있습니다:

  • 처음에 isPlayerAtrue입니다. 따라서 첫 번째 위치에는Counter상태가 있고, 두 번째 위치는 비어 있습니다.
  • "Next player" 버튼을 클릭하면 첫 번째 위치는 비워지지만 두 번째 위치에 이제Counter가 들어갑니다.
React 컴포넌트 트리 다이어그램. 부모는 'Scoreboard'로 레이블되어 있고 'isPlayerA'라는 상태 버블이 있으며 값은 'true'입니다. 유일한 자식은 왼쪽에 배치되어 있으며 'Counter'로 레이블되어 있고 'count'라는 상태 버블이 있으며 값은 0입니다. 왼쪽 자식 전체가 노란색으로 강조되어 추가되었음을 나타냅니다.React 컴포넌트 트리 다이어그램. 부모는 'Scoreboard'로 레이블되어 있고 'isPlayerA'라는 상태 버블이 있으며 값은 'true'입니다. 유일한 자식은 왼쪽에 배치되어 있으며 'Counter'로 레이블되어 있고 'count'라는 상태 버블이 있으며 값은 0입니다. 왼쪽 자식 전체가 노란색으로 강조되어 추가되었음을 나타냅니다.

초기 상태

React 컴포넌트 트리 다이어그램. 부모는 'Scoreboard'로 레이블되어 있고 'isPlayerA'라는 상태 버블이 있으며 값은 'false'입니다. 상태 버블이 노란색으로 강조되어 변경되었음을 나타냅니다. 왼쪽 자식은 삭제되었음을 나타내는 노란색 'poof' 이미지로 대체되었고, 오른쪽에 새로운 자식이 추가되었음을 나타내는 노란색 강조 표시가 있습니다. 새로운 자식은 'Counter'로 레이블되어 있고 'count'라는 상태 버블이 있으며 값은 0입니다.React 컴포넌트 트리 다이어그램. 부모는 'Scoreboard'로 레이블되어 있고 'isPlayerA'라는 상태 버블이 있으며 값은 'false'입니다. 상태 버블이 노란색으로 강조되어 변경되었음을 나타냅니다. 왼쪽 자식은 삭제되었음을 나타내는 노란색 'poof' 이미지로 대체되었고, 오른쪽에 새로운 자식이 추가되었음을 나타내는 노란색 강조 표시가 있습니다. 새로운 자식은 'Counter'로 레이블되어 있고 'count'라는 상태 버블이 있으며 값은 0입니다.

"next" 클릭

React 컴포넌트 트리 다이어그램. 부모는 'Scoreboard'로 레이블되어 있고 'isPlayerA'라는 상태 버블이 있으며 값은 'true'입니다. 상태 버블이 노란색으로 강조되어 변경되었음을 나타냅니다. 왼쪽에 새로운 자식이 추가되었음을 나타내는 노란색 강조 표시가 있습니다. 새로운 자식은 'Counter'로 레이블되어 있고 'count'라는 상태 버블이 있으며 값은 0입니다. 오른쪽 자식은 삭제되었음을 나타내는 노란색 'poof' 이미지로 대체되었습니다.React 컴포넌트 트리 다이어그램. 부모는 'Scoreboard'로 레이블되어 있고 'isPlayerA'라는 상태 버블이 있으며 값은 'true'입니다. 상태 버블이 노란색으로 강조되어 변경되었음을 나타냅니다. 왼쪽에 새로운 자식이 추가되었음을 나타내는 노란색 강조 표시가 있습니다. 새로운 자식은 'Counter'로 레이블되어 있고 'count'라는 상태 버블이 있으며 값은 0입니다. 오른쪽 자식은 삭제되었음을 나타내는 노란색 'poof' 이미지로 대체되었습니다.

"next" 다시 클릭

Counter의 상태는 DOM에서 제거될 때마다 파괴됩니다. 이것이 버튼을 클릭할 때마다 리셋되는 이유입니다.

이 해결책은 같은 위치에 렌더링되는 독립적인 컴포넌트가 몇 개 없을 때 편리합니다. 이 예제에서는 두 개뿐이므로 JSX에서 각각을 별도로 렌더링하는 것은 번거롭지 않습니다.

옵션 2: key로 상태 리셋하기

컴포넌트의 상태를 리셋하는 또 다른, 더 일반적인 방법도 있습니다.

아마도 key목록을 렌더링할 때본 적이 있을 것입니다. 키는 목록만을 위한 것이 아닙니다! 키를 사용하여 React가 컴포넌트를 구분하도록 만들 수 있습니다. 기본적으로 React는 부모 내에서의 순서("첫 번째 카운터", "두 번째 카운터")를 사용하여 컴포넌트를 구분합니다. 하지만 키를 사용하면 React에게 이것이 단순히첫 번째 카운터나 두 번째카운터가 아니라 특정 카운터—예를 들어,Taylor의카운터—라고 알려줄 수 있습니다. 이렇게 하면 React는 트리 어디에 나타나든Taylor의카운터를 인식할 것입니다!

이 예제에서 두 개의<Counter />는 JSX에서 같은 위치에 나타나더라도 상태를 공유하지 않습니다:

Taylor와 Sarah 사이를 전환해도 상태가 유지되지 않습니다. 이는서로 다른 key를 부여했기 때문입니다:

제거될 때마다 그 상태가 파괴됩니다

참고

키는 전역적으로 고유하지 않다는 점을 기억하세요. 키는부모 내에서의위치만 지정합니다.

키로 폼 리셋하기

키로 상태를 리셋하는 것은 폼을 다룰 때 특히 유용합니다.

이 채팅 앱에서<Chat>컴포넌트는 텍스트 입력 상태를 포함합니다:

입력란에 무언가를 입력한 다음 "Alice" 또는 "Bob"을 눌러 다른 수신자를 선택해 보세요.<Chat>컴포넌트가 트리 내 동일한 위치에 렌더링되기 때문에 입력 상태가 유지되는 것을 확인할 수 있습니다.

많은 앱에서는 이 동작이 바람직할 수 있지만, 채팅 앱에서는 그렇지 않습니다!사용자가 실수로 클릭하여 이미 입력한 메시지를 잘못된 사람에게 보내도록 하고 싶지 않을 것입니다. 이를 수정하려면key를 추가하세요:

이렇게 하면 다른 수신자를 선택할 때Chat컴포넌트가 그 아래 트리의 모든 상태를 포함하여 처음부터 다시 생성됩니다. React는 DOM 요소를 재사용하는 대신 다시 생성합니다.

이제 수신자를 전환하면 항상 텍스트 필드가 지워집니다:

Deep Dive
제거된 컴포넌트의 상태 보존

요약

  • React는 동일한 컴포넌트가 동일한 위치에 렌더링되는 한 상태를 유지합니다.
  • 상태는 JSX 태그에 저장되지 않습니다. 해당 JSX를 배치한 트리 위치와 연결됩니다.
  • 서브트리의 상태를 재설정하려면 다른 key를 부여하면 됩니다.
  • 컴포넌트 정의를 중첩하지 마세요. 그렇지 않으면 실수로 상태가 재설정될 수 있습니다.

Try out some challenges

Challenge 1 of 5:Fix disappearing input text #

This example shows a message when you press the button. However, pressing the button also accidentally resets the input. Why does this happen? Fix it so that pressing the button does not reset the input text.