컴포넌트 함수가 실행되지 않기 때문에
일반적인 변수로
UI를 업데이트할 수 없습니다
대신 UI를 업데이트하고 싶다고
리액트에게 알려줄 방법을 찾아야 합니다
지난 수업 마지막에서 언급한 것 같이
State(상태)라는 또 다른 매우 중요한 개념으로
달성할 수 있습니다
이 개념은 리액트에서 처리되는
변수를 등록하는 것이며
리액트가 제공하는 함수의 도움을 받아
업데이트됩니다
또한 리액트에게 데이터가 변한 것을 알려주면
리액트가 UI를 업데이트합니다
이 특별한 변수들은
리액트 라이브러리에서 불러와야 하는
특별한 함수의 도움으로 생성됩니다
리액트에 중괄호 사이에 무언가를 불러오기 위해
import 문을 추가해줘야 합니다
그 무엇은 useState라는 함수입니다
이른바 리액트 Hook입니다
리액트 프로젝트에서 'use'로 시작하는 모든 함수는
리액트 Hooks입니다
이 리액트 Hook은 사실
일반 함수이지만 특별한 점은
리액트 컴포넌트 함수 또는
다른 리액트 Hook 안에서
호출되어야 합니다
나중에 배울 커스텀 리액트 Hook을
다른 리액트 Hook의 예로 들 수 있습니다
여기에 리액트 컴포넌트 함수인
App 컴포넌트 함수가 있습니다
이를 통해 useState를 부를 수 있습니다
이런 Hook 함수는 이런 식으로
컴포넌트 함수 안에서 바로 호출해야 하며
다른 코드 안에 중첩되면 안됩니다
이런 내부 함수 안에 중첩되면 안되는 것입니다
이는 허용되지 않으며
컴포넌트 함수의 최상위에서 호출해야 합니다
이것이 Hook의 중요한 두 가지 규칙이고
말한 것처럼 리액트 Hook 함수는
컨포넌트 함수 또는 커스텀 Hook 안에서
불러야 합니다
이 다소 상급인 기능은
나중에 살펴보겠습니다
그리고 최상위에서 호출해야 하는데
다른 내부 함수에 중첩되거나
if문 또는 loop도 안됩니다
그래서 이렇게 Hook 함수를 부릅니다
차후에 내장 Hook 함수를 배우고
여러분 자신의 함수를 구축하는 방법도 배울 것입니다
이 useState Hook은
리액트에서 제공하는 가장 중요한 Hook 중 하나입니다
일부 컴포넌트에 연결된 상태를
관리하게 하기 때문입니다
이는 리액트에 의해 저장된 일부 데이터일 뿐이며
데이터가 변경되면 이 Hook이
자신이 속한 컴포넌트 함수를 활성화하여
리액트에 의해 재검토됩니다
여기에서 가장 필요한 것입니다
useState는 인수를 받아들이는데
이는 기본적으로 컴포넌트가 처음 렌더링될 때
여러분이 리액트가 저장하고
사용하길 원하는 기본값이라고 할 수 있습니다
나중에 변경하긴 하지만
지금으로선 초기 값으로
'Please click a button'(버튼을 클릭해주세요) 텍스트를 넣습니다
그러면 useState가 값을 반환하는데
이는 변수 또는 상수에
저장할 수 있습니다
반환되는 이 값은 사실
배열입니다
이 배열에는 요소가 정확히 2개가 있는데
useState를 사용할 때 나오는 요소는
항상 2개입니다
그러므로 여기서 일반 자바스크립트 기능인
배열 구조 분해를 이용해 이 2개의 요소를
2개의 별도 상수에 저장할 수 있습니다
반환된 배열에서 추출하는
이 두 요소의 이름은
여러분이 자유롭게 정하셔도 됩니다
저는 이 첫 요소를 selectedTopic이라고
부를 것인데 버튼을 누를 때
결국 한 개의 주제(topic)를
고르는(select) 것이기 때문입니다
여기 두 번째 요소는 setSelectedTopic이라고 부를 것입니다
말했듯이 이름은 여러분이 자유롭게 정할 수 있으나
제가 지금같이 이름을 정하는 방식은
거의 모든 리액트프로젝트에서 볼 수 있는
일반적인 명명 규칙입니다
여기서 첫 번째 요소의 이름은 selectedTopic입니다
useState에서 반환된
이 배열의 첫 번째 요소는
이 컴포넌트 실행 주기의
현재 데이터 스냅샷이 된다다고 볼 수 있습니다
그리하여 컴포넌트 함수가 처음 실행될 때
이 초기 값이
selectedTopic에 저장됩니다
무슨 이유인지 다시 실행될 때는
업데이트 된 값이 저장됩니다
그러니 실질적으로 관리하는 데이터는
이 첫 번째 요소입니다
이 두 번째 요소의 이름은 setSelectedTopic으로 정했는데
useState에서 반환된 배열의
두 번째 요소는
항상 함수이기 때문입니다
이 함수는 리액트에서 제공되고
이 상태를 업데이트하기 위해 실행되어
이 저장된 값을 업데이트합니다
이 저장된 값을 업데이트하는 것 외에도
여기에 있는 이 두 번째 요소인 이 특수 함수를 호출하면
React에 여기에 있는 이 컴포넌트 함수를
다시 실행해야 함을 알려줍니다
이전에 결여되었던 부분이기 때문에
여기서 아주 중요합니다
이 UseState Hook을 통해 리액트에게
이 컴포넌트 함수가 다시 실행되야 한다고 알릴 수 있습니다
그렇기 때문에 여기에 const를 사용할 수 있는데
selectedTopic와 같은 상수가
컴포넌트 함수를 실행할 때마다
다시 생성되므로
여기서 변수를 사용할 필요가 없습니다
그러나 배후에서 리액트가 실제 값을
저장하고 업데이트한 다음
이 컴포넌트 함수가 다시 실행될 때
이 상수에 전달됩니다
그러므로 handleSelect에서
여기서는 setSelectedTopic 이름을 변경합니다
selectedButton 값을 설정합니다
그러면 아래에 selectedTopic을 출력할 수 있습다
이 것이 useState 배열에서 반환된
첫 번째 요소 즉, 상태 스냅샷입니다
그것이 여기에 중괄호로
출력 중인 것입니다
추가로 selectedTopic을console.log할 것인데
여기에 로그를 출력하면
아주 신기한 것이 나타나기 때문입니다
일단 여기까지 저장하고 새로고침합니다
이제 Components를 클릭하면
여기 텍스트가 'Components'로 변경되었습니다
JSX를 클릭하면 'jsx'로 변경됩니다
이런 식으로 드디어 UI를 업데이트 할 수 있습니다
지금까지 상호작용하고 동적인 UI를 만들기 위한
기능에 있어 결여된 부분이었기 때문에
이제 한 걸음 더 도약하였습니다
그러나 좀 전에 말했듯이 신기한 것이 있습니다
페이지를 새로고침하고
Components 또는 다른 버튼을 클릭합니다
보시다시피 UI가 업데이트되고
그로 인해 Component 실행 로그가
다시 출력됩니다
여기에 먼저 출력되고
여기에 다시 출력됩니다
App 컴포넌트 함수가 재실행됐기 때문인데
App 컴포넌트 안에서
TapButton 컴포넌트를 사용하기 때문에
이 TapButton 컴포넌트 함수도 다시 실행된 것입니다
로그에서도 보실 수 있습니다
이것이 초기 상태값입니다
이제 콘솔을 비우고 보면
버튼을 누를 때마다
UI에는 올바른 값이 보이지만
콘솔에는 예전 값이 출력되는 것이 보입니다
즉, 상태를 업데이트 했어도 로그를 출력하면
상태를 변경하기 전의 상태 값이 나오는 것입니다
이를 알기 위해 리액트가 내부적으로
작동하는 원리를 이해해야 합니다
setSelectedTopic을 부를 때
즉,상태를 업데이트 시키는 함수를 부를 때
리액트는 이 상태 업데이트의 스케줄을 조정하며
이 컴포넌트 함수를 재실행합니다
그래서 App 컴포넌트 함수를 다시 실행하고 나서야
업데이트된 값을 사용할 수 있습니다
그제서야 새로운 값을 사용할 수 있으므로
업데이트의 스케줄이 조정되자마자 로그를 출력하면
보이지 않는 것입니다
다시 말해 아직은 예전 App 함수에 있다는 것입니다
그래서 그것을 꼭 기억해야 합니다
이로써 상태를 관리하는 방법과
상호작용하는 UI를 구축하는 방법을 배웠습니다
이 지식을 계속 사용해
이 예시를 계속 작업할 것이고
더 의미 있는 내용을 출력할 예정입니다