리액트에서 State
란 가장 중요한 개념이다.
State
는 Component
를 다시 렌더링하고 화면에 표시되는 것들을 바꾼다.
즉, Component와 State의 상호작용은 리액트의 핵심적인 개념이다.
이 둘을 리액트가 관리하는 것에 주목해야할 필요가 있다.
컴포넌트의 개념은 리액트 라이브러리에서 나왔으며, 리액트는 이 컴포넌트와 연결된 상태도 함께 처리한다.
useState가 그 예시이다.
useState는 리액트가 제공하며, 리액트는 State를 관리한다.
리액트는 State를 관리하고 컴포넌트와의 연결을 관리한다.
관리 프로세스의 일부로 리액트는 useState와 여기에 전달된 기본값에 대해서는 한 번만 고려되도록 처리한다.
컴포넌트가 처음 렌더링 될 때 useState
가 실행되면 리액트가 관리하는 새로운 State 변수를 만들게 된다.
그 후, 리액트는 이 State 변수가 어느 컴포넌트에 속하는지 기억해둔다.
그리고 기본값을 사용하여 State값을 초기화한다.
이후, 해당 함수 컴포넌트의 호출(=== 컴포넌트를 재평가하는 과정)
에서 useState
가 호출되면 새로운 상태는 생성되지 않는다.
이 때 리액트는 해당 컴포넌트에 대한 State가 이미 존재함을 알게되고, 필요할 경우 이 State를 업데이트하게 된다.
⭐️ 리액트는 State 관리와 업데이트만을 담당한다.
컴포넌트가 DOM에서 완전히 삭제되거나 하지 않는 이상 State 초기화는 이루어지지 않는다.
⭐️ 단, 컴포넌트가 조건부로 생성되었다가 없어지는 등이라면 새로운 State가 초기화될 수 있다.
하지만 DOM에 컴포넌트가 연결되고 유지되는 동안에는 State는 최초의 초기화 이후에는 업데이트만 된다.
+ useReducer의 경우에도 동일하다.
컴포넌트 안에 useState
Hook을 통해 일부 State를 관리할 수 있다.
즉, 리액트가 State를 관리해주고 있다.
setState(상태 업데이트 함수)
를 호출하면 setState()
안에 있는 데이터로 State 업데이트를 하게끔 예약하게 된다.
어디선가 loginHandler()
함수가 실행된다면, 상태 업데이트 함수인 setIsLogin()
가 실행되어 이전 스냅샷과 비교하여 반대되는 값을 return하게 된다. 이것은 즉시 실행되어 바로 값을 업데이트하는 것이 아니라, State 업데이트를 예약한 것이다.
해당 개념이 상태 갱신 예약(State Update Change)
이다.
리액트는 State의 변화를 인지하고 있고, 처리할 계획을 준비한다.
즉, State 업데이트를 즉시 처리하지 않는다. (업데이트를 하려고 예약한다.)
State 업데이트의 대한 스케줄 작업은 매우 빠르게 발생하기 때문에 즉시 실행되는 것처럼 보이지만, 사실은 예약 후에 처리되는 프로세스를 가지고있다.
언젠가 예약되어진 State 업데이트 과정이 처리되면 State는 변경될 것이다.
이 때, 리액트는 컴포넌트를 재평가하기 시작하고, 컴포넌트 함수를 재실행한다.
다수의 State Change가 스케줄링 때문에 예약되있을 수 있다.
이 때문에 동시에 여러번의 업데이트가 스케줄될 수 있으므로 State를 업데이트 할 때, 함수 형태를 이용해서 갱신하는 것을 권장한다.
(위 예시 코드처럼)
특히 이전 상태의 스냅샷에 의존해야 하는 경우
이렇게 하지 않으면 컴포넌트 함수가 마지막으로 실행될 때의 State를 얻게 된다.
이것은 State 변경이 순서대로 실행될 때와는 다른 결과가 나올 수도 있다.
완료되지 않은 상태 변경 작업이 여러개가 있다면 해당 컴포넌트의 리렌더링 주기는 모두 동일하기 때문이다.
컴포넌트 함수는 모두 최종 컴포넌트 스냅샷으로부터 발생하지만, 변경 작업이 처리된 경우에는 컴포넌트는 중간에 다시 렌더링된다.
하지만 변경 작업들은 이미 예약이 되어있으므로 완료되지 않은 상태 변경 작업은 새로운 컴포넌트의 결과를 고려하지 않게 된다.
함수 형태를 사용해야 리액트가 미완료된 상태 변경 작업에 대하여 최신의 상태를 사용할 수 있고, 컴포넌트가 리렌더링 되었을 때에 예전 시점의 상태를 사용하지 않게 된다.
또한 데이터 없이 작업을 할 때 발생할 수 있는 잠재적인 위험을 배제할 수 있다.컴포넌트가 리렌더링 되었을 때의 시점과 상태 변경이 예약되는 시점의 차이를 아는 것은 매우 중요하다.
하나의 컴포넌트가 재평가되면서 미완료된 상태 변경 작업이 여러 개 있을 수 있다.
때문에 함수 형태를 이용해서 업데이트 하는 것이 중요한 이유이다.
추가적으로 useEffect
내부에서 이메일과 비밀번호의 유효상태를 통해 Form의 유효성을 업데이트하는 것이 안전하다.
이전 상태의 스냅샷을 기반으로 상태를 업데이트하기 위해 함수 형식을 사용하는 것과 비슷하게 사용한다.
useEffect는 상태 또는 종속된 값이 변경될 때마다 의존성 메커니즘을 통해 내부에서 선언한 이펙트(useEffect 내부 코드
)가 재실행되게끔 한다.
따라서 컴포넌트 함수가 재실행되고 컴포넌트가 재실행되므로 매번 이펙트가 다시 실행되기 때문에 미완료된 상태 변경 작업이 빠짐없이 실행된다.