파트 3

3.0 파트 3 (클릭 가능)

마운트(Mount)

componentMount 메소드는 이 여정에서 가장 큰 부분 중 하나입니다! 그래서, ReactCompositeComponent.mountComponent(1)는 흥미로운 메소드 입니다.

기억하시겠지만, 컴포넌트의 트리에 처음 삽입되는 컴포넌트는TopLevelWrapper(내부 리엑트 클래스)라고 한 적이 있었습니다. 이제 그것 마운팅 하려고 합니다. 하지만, 이건 사실 비어있는 래퍼이므로 디버깅이 좀 지루합니다. 지금 흐름에 전혀 영향을 주지 않기 때문에 지금은 이걸 건너 뛰고 자식으로 이동하겠습니다.

부모와 그 부모의 자식, 그 자식의 자식을 계속해서 마운트하는 것이 트리의 마운팅이 실제로 하는 일입니다. 저를 믿으세요, TopLevelWrapper가 마운트 된 후에, 그것(ExampleApplication 컴포넌트를 관리하는ReactCompositeComponent)의 자식도 같은 단계에 놓이게됩니다.

좋습니다, 이제 다시 step(1)로 돌아갑시다. 안에 뭐가 있는지 봅시다. 몇 가지 주요 동작이 발생하므로, 자세하게 이 로직을 살펴 보겠습니다.

인스턴스 updater 할당

transaction.getUpdateQueue()에서 리턴되는 updater(2)는 사실 ReactUpdateQueue 모듈입니다. 그런데 updater가 왜 여기서 할당될까요? ReactCompositeComponent(우리가 현재보고있는 클래스)는 모든 플랫폼에서 사용되지만, updater는 그렇지 않기 때문에 플랫폼에 따라 마운팅되는 동안 동적으로 할당합니다.

지금은 updater가 필요하지 않지만 기억해 두십시오. updater는 정말 중요합니다. 잘 알려진 컴포넌트 메소드인 setState에 의해 곧 사용될 것입니다.

이 단계에서 인스턴스에 updater가 할당될뿐만 아니라 컴포넌트 인스턴스(사용자 정의 컴포넌트)도 props, context, refs로 확장됩니다.

아래 코드를 확인하십시오 :

// \src\renderers\shared\stack\reconciler\ReactCompositeComponent.js #255
// 이것들은 생성자안에서 설정되어야하지만,  
// 좀더 단순한 클래스 추상화의 편의를 위해, 생성자 이후에 설정했다.
inst.props = publicProps;
inst.context = publicContext;
inst.refs = emptyObject;
inst.updater = updateQueue;

이제, this.props로 인스턴스의 props에 접근 할 수 있습니다.

ExampleApplication 인스턴스 생성

_constructComponent(3)을 호출하고 여러 가지 구성 메소드를 통해 마침내 new ExampleApplication()이 생성됩니다. 생성자가 호출 될 때가 중요합니다. 이 시점이 리엑트의 생태계로 부터 실제로 영향을 받은 첫번째 순간 입니다.

초기 마운트 수행

mount(4)를 지나면, 먼저 componentWillMount(명시된 경우)가 호출됩니다. 이건 라이프 사이클 훅의 첫 번째 메소드입니다. 또한, 뒤에서 componentDidMount를 볼 수 있지만 직접 호출되어서는 안되기 때문에 트랜잭션 대기열에 넣습니다. 이건 마운트 작업이 끝나는 마지막에만 발생합니다. setState 호출은 componentWillMount 안에서도 할 수 있습니다. 이 경우에는 render메소드 없이 state가 다시 계산됩니다.(컴포넌트가 아직 마운트되지 않았기 때문에 state를 알 수 없습니다).

공식 문서에서 다음과 같이 작성되어 있습니다:

componentWillMount()는 마운트가 일어나기 직전에 호출된다. render()전에 호출되기 때문에, 이 메소드의 state를 설정해도 리렌더링이 발생되지 않는다.

코드를 확인해 봅시다.

// \src\renderers\shared\stack\reconciler\ReactCompositeComponent.js #476
if (inst.componentWillMount) {
    //..
    inst.componentWillMount();

    // 마운트 할 때,`componentWillMount`에 의한 `setState`호출은 리렌더링을 하지 않고,
    // `this._pendingStateQueue`를 설정합니다.
    if (this._pendingStateQueue) {
        inst.state = this._processPendingState(inst.props, inst.context);
    }
}

state가 다시 계산 될 때 render메소드를 호출합니다. 정확히는 사용자가 컴포넌트에서 지정하는 것입니다! 이제 한번 더 코드에 손대봅시다.

다음은 리엑트 컴포넌트 인스턴스를 만드는 것입니다. 또 하는것 같나요? 이미 this._instantiateReactComponent(5) 호출을 본 것 같습니다. 맞나요? 사실이지만, 그때는 ExampleApplication 컴포넌트에 대해 ReactCompositeComponent를 인스턴스화했습니다. 이제 render메소드에서 얻은 엘리먼트를 기반으로 그 자식에 대한 VDOM 인스턴스를 생성 할 것입니다. 정확하게는 render 메서드는 div를 반환하므로 VDOM 표현은 ReactDOMComponent입니다. 인스턴스가 생성되면, ReactReconciler.mountComponent를 다시 호출합니다. 하지만 이번에는 internalInstance로 새로 생성 된 ReactDOMComponent의 인스턴스를 전달합니다.

그리고,mountComponent를 호출합니다.

좋습니다, 이제 우리는 파트 3를 끝냈습니다.

우리가 어떻게 여기까지 왔는지 다시 한번 살펴보도록 합시다. 스키마에서 덜 중요한 부분을 제거하면 다음과 같습니다.

3.1 간단히 보는 파트 3 (클릭 가능)

공백제거와 정렬을 통해 보기 좋게 수정했습니다.

3.2 간단히 보는 파트 3 리펙토링 버전 (클릭 가능)

좋습니다. 사실, 이것이 여기서 일어나는 일 전부입니다. 이제 파트 3의 핵심들을 가지고 최종 mounting 스키마에 사용할 수 있습니다.

3.3 파트 3의 핵심 (클릭 가능)

그리고 이제 우리는 해냈습니다!

다음 페이지 : 파트 4 »

« 이전 페이지 : 파트 2