State: 컴포넌트의 기억 저장소
일반 변수로 충분하지 않은 경우
다음은 조각상 이미지를 렌더링하는 컴포넌트입니다. “Next” 버튼을 클릭하면 index
를 1
, 2
로 변경하여 다음 조각상을 표시해야 합니다. 그러나 이것은 작동하지 않습니다 (시도해 보세요!)
handleClick
이벤트 핸들러는 지역 변수 index
를 업데이트하고 있습니다. 하지만 이러한 변화를 보이지 않게 하는 두 가지 이유가 있습니다.
- 지역 변수는 렌더링 간에 유지되지 않습니다. React는 이 컴포넌트를 두 번째로 렌더링할 때 지역 변수에 대한 변경 사항은 고려하지 않고 처음부터 렌더링 합니다.
- 지역 변수를 변경해도 렌더링을 일으키지 않습니다. React는 새로운 데이터로 컴포넌트를 다시 렌더링해야 한다는 것을 인식하지 못합니다.
컴포넌트를 새로운 데이터로 업데이트하기 위해선 다음 두 가지가 필요합니다.
- 렌더링 사이에 데이터를 유지합니다.
- React가 새로운 데이터로 컴포넌트를 렌더링하도록 유발합니다.
훅은 이 두 가지를 제공합니다.
- 렌더링 간에 데이터를 유지하기 위한 state 변수.
- 변수를 업데이트하고 React가 컴포넌트를 다시 렌더링하도록 유발하는 state setter 함수
state 변수 추가하기
state 변수를 추가하려면 파일 상단의 React에서 useState
를 가져옵니다.
그런 다음 이 줄을
다음과 같이 바꿉니다.
index
는 state 변수이고 setIndex
는 setter 함수입니다.
여기서
[
와]
문법을 라고 하며, 배열로부터 값을 읽을 수 있게 해줍니다.useState
가 반환하는 배열에는 항상 두 개의 항목이 있습니다.
이것이 handleClick
에서 함께 작동하는 방식입니다
이제 “Next” 버튼을 클릭하면 현재 조각상을 전환합니다.
첫 번째 훅 만나기
React에서 useState
와 같이 “use
”로 시작하는 다른 모든 함수를 훅이라고 합니다.
훅은 React가 오직 중일 때만 사용할 수 있는 특별한 함수입니다. (이에 대해서는 다음 페이지에서 자세히 알아보겠습니다) 이를 통해 다양한 React 기능을 “연결”할 수 있습니다.
State는 이러한 기능 중 하나일 뿐이며, 나중에 다른 훅들을 만나게 됩니다.
useState
해부하기
를 호출하는 것은, React에 이 컴포넌트가 무언가를 기억하기를 원한다고 말하는 것입니다.
이 경우 React가 index
를 기억하기를 원합니다.
useState
의 유일한 인수는 state 변수의 초깃값입니다. 이 예시에서 index
의 초깃값은 useState(0)
에 의해 0
으로 설정됩니다.
컴포넌트가 렌더링될 때마다, useState
는 다음 두 개의 값을 포함하는 배열을 제공합니다.
- 저장한 값을 가진 state 변수 (
index
). - state 변수를 업데이트하고 React에 컴포넌트를 다시 렌더링하도록 유발하는 state setter 함수 (
setIndex
).
실제 작동 방식은 다음과 같습니다.
- 컴포넌트가 처음 렌더링 됩니다.
index
의 초깃값으로useState
를 사용해0
을 전달했으므로[0, setIndex]
를 반환합니다. React는0
을 최신 state 값으로 기억합니다. - state를 업데이트합니다. 사용자가 버튼을 클릭하면
setIndex(index + 1)
를 호출합니다.index
는0
이므로setIndex(1)
입니다. 이는 React에index
는1
임을 기억하게 하고 또 다른 렌더링을 유발합니다. - 컴포넌트가 두 번째로 렌더링 됩니다. React는 여전히
useState(0)
를 보지만,index
를1
로 설정한 것을 기억하고 있기 때문에, 이번에는[1, setIndex]
를 반환합니다. - 이런 식으로 계속됩니다!
컴포넌트에 여러 state 변수 지정하기
하나의 컴포넌트에 원하는 만큼 많은 타입의 state 변수를 가질 수 있습니다. 이 컴포넌트는 숫자 타입 index
와 “Show details”를 클릭했을 때 토글 되는 불리언 타입인 showMore
라는 두 개의 state 변수를 가지고 있습니다.
이 예시에서 index
와 showMore
처럼 서로 연관이 없는 경우 여러 개의 state 변수를 가지는 것이 좋습니다. 하지만 두 state 변수를 자주 함께 변경하는 경우에는 두 변수를 하나로 합치는 것이 더 좋을 수 있습니다. 예를 들어, 필드가 많은 폼의 경우 필드별로 state 변수를 사용하는 것보다 하나의 객체 state 변수를 사용하는 것이 더 편리합니다. 더 많은 팁은 에서 확인할 수 있습니다.
자세히 살펴보기
React는 어떤 state를 반환할지 어떻게 알 수 있을까요?
React는 어떤 state를 반환할지 어떻게 알 수 있을까요?
useState
호출이 어떤 state 변수를 참조하는지에 대한 정보를 받지 못한다는 것을 눈치채셨을 것입니다. useState
에 전달되는 “식별자”가 없는데 어떤 변수를 반환할지 어떻게 알 수 있을까요? 함수를 파싱하는 것과 같은 마법에 의존할까요? 대답은 ‘아니오’ 입니다.
대신 간결한 구문을 구현하기 위해 훅은 동일한 컴포넌트의 모든 렌더링에서 안정적인 호출 순서에 의존합니다. 위의 규칙(“최상위 수준에서만 훅 호출”)을 따르면, 훅은 항상 같은 순서로 호출되기 때문에 실제로 잘 작동합니다. 또한, 은 대부분의 실수를 잡아줍니다.
내부적으로 React는 모든 컴포넌트에 대해 한 쌍의 state 배열을 가집니다. 또한 렌더링 전에 0
으로 설정된 현재 인덱스 쌍을 유지합니다. useState
를 호출할 때마다, React는 다음 state 쌍을 제공하고 인덱스를 증가시킵니다. 이 메커니즘에 대한 자세한 내용은 에서 확인할 수 있습니다.
이 예시에서는 React를 사용하지 않지만, 내부적으로 useState
가 어떻게 작동하는지에 대한 아이디어를 제공합니다.
이해하지 않아도 React를 사용하는 데 문제는 없지만, 도움이 되는 사고방식으로서 유용할 수 있을 것입니다.
State는 격리되고 비공개로 유지됩니다
State는 화면에서 컴포넌트 인스턴스에 지역적입니다. 다시 말해, 동일한 컴포넌트를 두 번 렌더링한다면 각 복사본은 완전히 격리된 state를 가집니다! 그중 하나를 변경해도 다른 하나에는 영향을 미치지 않습니다.
이 예시에서 이전에 나왔던 Gallery
컴포넌트가 로직 변경 없이 두 번 렌더링되었습니다. 각각의 갤러리 내부 버튼을 클릭해 보세요. 그들의 state가 서로 독립적임을 주목하세요.
이것이 state를 일반적인 모듈 상단에 선언할 수 있는 보통의 변수와 구별하는 요소입니다. State는 특정 함수 호출이나 코드 내의 특정 위치와 관련이 없습니다. 대신, 화면의 특정 위치에 “지역적”입니다. <Gallery />
컴포넌트를 두 번 렌더링했으므로 그들의 state는 별도로 저장됩니다.
또한 Page
컴포넌트가 Gallery
의 state에 대해 아무것도 “알지” 않는다는 점과 심지어 그것이 있는지도 모른다는 것에 주목하세요. Props와 달리, state는 선언한 컴포넌트에 완전히 비공개입니다. 부모 컴포넌트는 이를 변경할 수 없습니다. 이로써 다른 컴포넌트에 영향을 미치지 않고 어떤 컴포넌트에든 state를 추가하거나 제거할 수 있게 됩니다.
만약 두 개의 갤러리가 state를 동기화하길 원한다면, React에서 올바른 방법은 자식 컴포넌트에서 state를 제거하고 가장 가까운 공통 부모 컴포넌트에 추가하는 것입니다. 다음 몇 페이지는 단일 컴포넌트의 state 구성에 중점을 두겠지만, 이 주제는 에서 다시 다룰 것입니다.
요약
- 컴포넌트가 렌더링 간에 어떤 정보를 “기억”해야 할 때 state 변수를 사용합니다.
- state 변수는
useState
훅을 호출하여 선언합니다. - 훅은 use로 시작하는 특별한 함수들입니다. 이들은 state와 같은 React 기능에 “연결”할 수 있도록 해줍니다.
- 훅은 import와 마찬가지로 반드시 호출되어야 합니다.
useState
를 포함한 훅을 호출하는 것은 컴포넌트나 다른 훅의 최상위 수준에서만 유효합니다. useState
훅은 현재 state와 이를 업데이트할 함수로 이루어진 한 쌍을 반환합니다.- 여러 개의 state 변수를 가질 수 있습니다. React 내부에서는 그들을 순서대로 매칭합니다.
- state는 컴포넌트에 비공개입니다. 두 곳에서 렌더링하더라도 각각의 복사본은 고유한 state를 가집니다.