React 알아가기 (10)

삔아·2023년 6월 13일
0
post-thumbnail

해당 내용은 https://www.udemy.com/course/best-react/ 강의를 들으며 정리하고 스스로 공부 한 내용을 기록 하였습니다.

About State

useState 를 통해 컴포넌트와 상태간의 상호 작용을 처리한다.

useState 는 리액트가 제공하고 있으며 리액트는 상태를 관리하고 컴포넌트와의 연결을 관리한다. 그리고 이 관리 프로세스의 일부로 리액트는 useState 와 여기에 전달 된 기본 값 에 대해서는 컴포넌트가 처음 렌더링 될 때, 한 번만 고려되도록 처리한다.

useState 가 실행 되면 리액트가 관리하는 새로운 상태변수를 만들게 되며 리액트는 이 변수가 어느 컴포넌트에 속하는지를 기억해둔다.
그리고 기본 값을 사용하여 상태 값을 초기화 한다.
이 후, 해당 컴포넌트를 재평가 하는 과정에서 useState 가 호출 되면 리액트는 이 컴포넌트에 대한 상태가 이미 존재함을 깨닫고 필요한 경우에만 상태를 업데이트 할 뿐 새로운 상태는 생성되지 않는다.

리액트는 상태의 관리와 갱신만을 담당한다.

컴포넌트가 DOM에서 완전히 삭제되지 않는 이상 상태의 초기화는 이루어지지 않는다.
다시 말하면, DOM에 컴포넌트가 연결되고 유지되는 동안에는 상태는 최초의 초기화 이후엔 갱신만 된다는 것이다.

그렇다면 리액트가 상태에 대한 갱신을 어떻게 할까.

State 스케줄링 및 일괄 처리

컴포넌트 안에는 useState 훅을 통해 일부 상태들을 리액트가 관리 할 수 있다.

예를들어, 하나의 컴포넌트의 초기 상태가 DVD 라고 가정하며, useState 를 통해 값을 반환하는 상태 갱신 함수를 setNewProduct 라고 하자.
이제 여기서 DVD 가 아닌 Book 으로 상태를 변경을 할 때, setNewProduct 는 실행이 완료 되었지만 상태 DVD는 즉각적으로 바뀌지 않는다.
대신, setNewProduct 를 호출하고 상태 업데이트 함수를 호출하면 Book 이라는 데이터로 상태 업데이트를 하게끔 예약을 한다.
이러한 것이 상태 갱신 예약 이다.

리액트는 상태 갱신을 인지하고 있고, 처리할 계획을 준비하지만 즉시 처리하지 않는다.
실제로는 순간적으로 발생하며, 거의 즉시 작업이 처리 된 것으로 보이지만 리액트는 이 상태 변화를 지연 시킨다.

대다수의 성능 기반 작업들이 거의 동시에 진행되는데 잠재적으로 리액트는 더 높은 우선 순위를 갖는것으로 간주한다.

예를 들어, 화면에 사용자가 입력 할 수 있는 공간이 있을 때, 사용자 입력에 응답하는 것이 화면의 문자를 변경하는 것 보다는 더 우선순위가 높을 것이다.
이러한 이유로 리액트는 예정된 상태 변경을 연기할 수 있다.

리액트는 상태 변화가 발생하게 되면 이 상태 변화의 순서를 명확히 해서 같은 타입 임을 보장 한다.

위의 예시를 다시 가져와서, 만약 setNewProduct 를 호출하여 Carpet 으로 바꾼다고 가정할 때,
상태 변화는 이전의 상태 변화 전 까지 일어나지 않는다. 즉, 순서가 유지 된다.

즉각 실행이 필수적인 것은 아니며, 결국 언젠가는 처리가 되고 상태는 책으로 바뀌며, 새로운 상태 변화가 처리가 되면 리액트가 컴포넌트를 재평가 하고 컴포넌트 함수를 재실행 한다.

이러한 스케줄링 때문에 다수의 예약 상태 변화가 동시에 있거나, 동시에 여러번의 갱신이 스케줄 될 수 있으므로 상태를 갱신할 때는 함수 형태를 이용해서 갱신 하는 것을 추천 한다. (특히, 이전 상태의 스냅샷에 의존 해야 할 때)

함수 형태를 사용해야 리액트가 미완료된 상태 변경 작업에 대하여 최신의 상태를 사용하고 컴포넌트가 재 렌더링 되었을 그 시점의 상태를 사용하지 않게 된다.

컴포넌트가 재 렌더링 되었을 때의 시점과 상태 변경이 예약 되는 시점의 차이를 아는 것이 포인트다.

하나의 컴포넌트가 재평가 되면서 미완료된 상태 변경 작업이 여러개 있을 수 있다.

...
const [drawerIsOpen, setDrawerIsOpen] = useState(false);
const [currentNavPath, setCurrentNavPath] = useState('example');

const navi = (path) => {
	setCurrentNavPath(path);
	// State was NOT Updated here
	setDrawerIsOpen(false);
};
...

위 예시 처럼 두 개의 상태 업데이트 함수를 호출 했을 때, 바로 다음 행에서 상태가 갱신되는 것이 아니라는 것을 알았다.

state 는 이 위치에서 갱신되지 않으며 갱신 예약을 한 후 컴포넌트가 다시 실행 한다.
이 경우에는 컴포넌트가 다시 실행되고 나서야 사용 가능한 최신 상태가 된다.

이렇게 두 개의 상태 갱신이 같은 코드 조각에 존재하는 것 처럼, 같은 함수가 서로 다른 프로미스에 있지 않고 같은 곳에 존재한다면 이 둘 사이에 시간 지연 현상은 발생하지 않는다.

두 개의 상태 갱신 함수가 같은 코드 조각에 있을 때, 리액트는 이들에 대한 상태 갱신을 하나의 동기화 프로세스에서 같이 실행한다.

만약 하나의 함수가 처음부터 끝 까지 어떠한 콜백이나 프로미스 없이 실행 된다면 리액트는 이 함수로부터 발생하는 모든 상태 갱신 작업을 하나의 상태 갱신 작업으로 처리하게 된다.

profile
Frontend 개발자 입니다, 피드백은 언제나 환영 입니다

0개의 댓글