리액트는 처음 마운트 되기 전에 렌더링이 중단된다면, 어떤 상태도 보존하지 않는다. 컴포넌트가 로드되면 리액트는 중단된 트리를 처음부터 렌더링을 시도한다.
컴포넌트는 컴포넌트 내부에서 startTransition이나 useDeferredValue로 인한 업데이트가 아닌 경우라면 fallback이 표시된다.
컴포넌트가 다시 일시 중단되었기 때문에 이미 보여진 컨텐츠를 감출 필요가 있다면, layout effect를 비운다. 다시 컨텐츠를 보여줄 준비가 됐을 때, 리액트는 layout effect를 발생시킨다. 이는 컨텐츠가 숨겨진 동안 DOM layout을 측정하지 않도록 한다.
처음에 Biography가 로딩이 완료 되지 않았을 때, BigSpinner가 fallback으로 보여지고, 이후 Biography는 로딩이 완료되었기 때문에 보여지고, 아래 Albums이 로딩이 완료되지 않았다면 AlbumsGlimmer를 보여주고 있다가 로딩이 완료되어 Albums를 보여준다.
앱의 규모가 커지고 복잡해짐에 따라 부모 컴포넌트에서 중첩된 자식 컴포넌트에게 데이터나 데이터 변경함수를 전달해줄 때, 몇단계를 걸쳐서 전달해줌으로서 애플리케이션이 더욱 복잡해지는 문제가 발생하였다.
이를 해결하기 위해 context API가 등장하였고, 이로써 props를 단계별로 넘겨주지 않아도 데이터를 제공할 수 있게 되었다. 그 결과 컴포넌트 트리로 묶인 컴포넌트 간 데이터 공유가 수월해졌다.
리액트에서 제공하는 내장 기능이다.
단, Context API를 사용하게 되면 컴포넌트의 재사용이 어려워지므로 꼭 필요한 경우에만 사용한다.
Redux란?
Redux는 action이라는 이벤트를 사용하여 데이터를 관리할 수 있는 상태관리 라이브러리이다.
리덕스의 3원칙
단 하나의 store에서 모든 상태가 저장된다.
store의 상태를 변경하는 유일한 방법은 action 객체를 dispatch하는 방법 뿐이다.
action에 의한 상태 변경은 순수함수를 통해서만 가능하도록 작성해야 한다.
리덕스 특징
thunk, saga와 같은 미들웨어를 추가적으로 설정할 수 있다. 비동기 처리를 Util로 처리 가능
constinner = () => { const b = 5; return a + b; };
return inner; };
const closure = outer();
closure();
소스코드 평가와 실행
1. 전역 코드 평가
전역 실행 컨텍스트 생성
var 키워드로 선언된 전역변수 outer는 전역 객체에 등록
const 키워드로 선언된 전역변수 closure는 선언적 환경 레코드에 등록
this는 전역 객체 바인딩
2. 전역 코드 실행 단계
outer 우항의 함수를 평가한 뒤, 메모리에 저장한 뒤 전역 객체에서 outer 식별자에 할당
closure 우항의 outer 함수를 전역 객체에서 찾아 호출
3. outer 함수 평가 단계
outer 함수 실행 컨텍스트 생성
outer 함수에서 선언된 변수 a, inner를 환경 레코드에 등록
outer 함수의 외부 렉시컬 환경 참조는 outer 변수에 할당된 익명함수 객체의 내부슬롯 [[Environment]]가 가리키는 외부 렉시컬 환경을 가리킨다.
4. outer 함수 실행 단계
outer 함수 환경 레코드의 변수 a에 값 3이 할당된다.
변수 inner에 익명 함수 객체의 참조값이 할당되고, 익명 함수 객체의 내부 슬롯 [[Environment]]은 정의된 outer 렉시컬 환경을 가리킨다.
5. 전역 코드 실행 단계 복귀
전역 렉시컬 환경의 선언적 환경 레코드에서 closure를 찾는다.
inner 함수 객체가 closure라는 식별자에 할당된다.
6. closure 함수 평가 단계
closure() 문이 실행되면서 closure의 실행 컨텍스트가 생성된다.
closure를 실행하기 위해 inner 함수 객체를 평가한다.
즉, closure() 평가단계 === inner() 평가단계
const로 선언된 변수 b가 closure 환경 레코드에 등록된다.
화살표 함수의 this는 함수가 정의될 때 상위 스코프의 this로 정적으로 결정된다.
7. closure 함수 실행 단계
closure 즉, inner 함수 내부 코드가 실행
b에 값 5가 할당되고 a+b를 수행하기 위해 스코프 체인에서 a를 찾는다.
closure 환경 레코드에는 a가 존재하지 않기 때문에 외부 렉시컬 환경 참조를 따라 익명함수 객체로 이동하고, 익명함수 객체의 [[Environment]]내부 슬롯이 가리키는 outer 함수 렉시컬 환경으로 이동된다. 결국 outer 환경 레코드에서 a를 찾을 수 있다.
a+b 연산을 수행하고 연산값을 반환한다.
8. closure 실행 컨텍스트 소멸
closure 함수 코드가 실행을 마치고 closure의 실행 컨텍스트가 pop 되어 더 이상 참조되지 않는 객체들은 Garbage Collector에 의해 메모리가 해제된다.
9. 전역 실행 컨텍스트 소멸
마지막으로 전역 실행컨텍스트가 pop 되어 참조될 수 있는 객체가 없기 때문에 모든 객체가 Garbage Collector에 의해 메모리가 해제된다.
이전에 선언을 하면 선언단계와 초기화 단계가 진행된다 그랬었는데, 이것도 초기화가 맞지만 const를 사용하기 위해서는 개발자가 직접 초기화를 해줘야한다. 만약 초기화를 해주지 않고 나중에 값을 할당한다는 것이 재할당으로 해석되기 때문이다.
재할당 금지
const 키워드로 선언한 변수에 원시값을 할당하면 값을 변경할 수 없다. 하지만 객체를 할당한 경우 값을 변경할 수 있다. 재할당 금지라는 말이 불변을 의미하지는 않는다. 왜냐하면 식별자가 가리키는 메모리 주소 공간은 참조값이 저장되어 있고 객체를 변경하여도 참조값은 변하지 않기 때문이다.
상수
변하지 않는 값을 사용하기 위해 우리는 상수를 사용한다.
주로 상수의 이름은 대문자로 사용한다. 원시값을 할당한 경우 원시값은 변경 불가능한 값이고 재할당이 금지되므로 할당된 값을 변경할 방법은 없다.