programming language/react

[React] ReactDOM.createRoot VS ReactDOM.render

공대키메라 2022. 7. 9. 23:36

저번에 어떤 오류에 대해서 내용을 찾다가 우연히 (우연찮게라는 말은 "우연히가 아닌" => "고의적으로" 라는 말입니다. ㅎㅎ)

 

ReactDOM.createRoot과 ReactDOM.render에 대해서 비교하는 글을 찾았다.

 

그래서 이번 시간에는 이에 대해서 읽어보는 시간을 가져보겠다.

 

해당 내용은 외국 사이트에서 영어로 되어 있는것을 필자가 한글로 정리한 것이다. 

 

출처:

https://dev.to/fromaline/reactdomcreateroot-reactdomrender-1jg6

https://blog.fearcat.in/a?ID=00001-3af04151-f7a0-467a-9068-dc3637befcd2 


ReactDOM.createRoot 🆚 ReactDOM.render

ReactDOM.createRoot는 무엇이고 ReactDOM.render와 어떻게 다른가?

 

React 18은 새로운 root API를 도입했다. 그러면 알아 봅시다!

👉 현재의 API (Current API)

명확한 render를 위해 우리가 원할 때 마다 container를 보내줘야만 했다.

 

const container = document.querySelector('#root');

// Initial render. Container is explicitly accessed.
ReactDOM.render(<App text="Hello" />, container);

// Subsequent renders. Container is explicitly accessed.
ReactDOM.render(<App text="Hello world!" />, container);

👉 ReactDOM.render는 어떻게 작동하나? (What does ReactDOM.render take?)

render 함수는 세 가지 인수를 가진다

 

  • rendering 할 render 함수
  • 안에 rendering될 DOM element
  • rendering이 발생한 후 실행될 함수

그리고 같은 container를 반환하지만, component와 함께 rendering된다. 

 

/**
* @param element - React element to be rendered
* @param container - DOM element to render in
* @param callback - function to be executed after render happens
* @return container - container with renderned component
*/
function render(element, container, callback) {
  // ...
}

👉 ReactDOM.render는 내부에서 어떻게 작동하나?(How does ReactDOM.render work under the hood?)

ReactDOM.render는 여러개의 validation check를 한다. 

 

  • container가 적합한 node인지
  • container가 이전에 createRoot로 넘겨지지 않았는지

그리고 나서 모든 받은 인수를 legacyRenderSubtreeIntoContainer로 넘긴다.

 

// simplified structure
function render(element, container, callback) {
  if (isValidContainer(element)) {
    throw Error('Target container is not a DOM element.');
  }

  if (isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined) {
    // don't throw an error, but logs it into console
    error('container was previously passed to ReactDOM.createRoot().');
  }

  return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
}

👉 새로운 API(New API)

새로운 API는 명확히 rendering하기 원할 때 마다 container 를 넘기는 이슈를 해결한다. 

 

// First, we create a root
const root = ReactDOM.createRoot(document.querySelector('#root'));

// Initial render. Container is implicitly accessed.
root.render(<App name="Hello" />);

// Subsequent renders. Container is implicitly accessed.
root.render(<App name="Hello world!" />);

👉 What does ReactDOM.createRoot take?

createRoot 함수는 오직 필요한 인수만 받는다. (DOM rendeirng하루 DOM element.)

그리고 render와 unmount method를 가진 RootType을 반환한다. 

 

추신. 또한 createRoot는 두번째 RootOptions 인수를 받는다. 하지만 나중에 이걸 설명할 것이다. \

 

/**
* @param container - DOM element to render in
* @param options - options, related to hydration
* @return RootType - instance of root
*/
function createRoot(container, options) {
  // ...
}

👉 ReactDOM.createRoot는 내부적으로 어떻게 작동하나?(How does ReactDOM.createRoot work under the hood?)

renderin함수 위에, createRoo는...

  • container가 body element가 아닌지 확인한다.
  • 더 자세한 경고를 준다. 

그리고 나서 createRoot는 새로운 ReactDOMRoot 객체를 생성한다. 그리고 그것을 반환한다.  legacyRenderSubtreeIntoContainer는 전혀 반환하지 않는다! 

// simplified structure
function createRoot(container, options) {
  if (isValidContainer(element)) {
    throw Error('Target container is not a DOM element.');
  }

  if (container.nodeType === 1 && container.tagName.toUpperCase() === 'BODY') {
    console.error('Creating roots directly with document.body is discouraged');
  }

  if (isContainerMarkedAsRoot(container) {
    if (container._reactRootContainer) {
      console.error('container was previously passed to ReactDOM.render().')
    } else {
      console.error('container has already been passed to createRoot() before.');
    }
  }

  return new ReactDOMRoot(container, options);
}

 

이제 old render와 새로운 createRoot 함수 사이에 중요한 차이점을 알았습니다!

 

만약 legacyRenderSubtreeIntoContainer와 ReactDOMRoot의 차이점을 더 알고싶다면 알려주세요!

 

추신. 이런 더많은 컨텐츠를 원하면 twitter에서 follow해 주세요! (Follow me on Twitter)


legacyRenderSubtreeIntoContainer라는 것도 사실 필자는 처음 알았고, ReactDOMRoot라는 것에 대해서도 처음 알았다.

 

그냥 사용만 할 줄 알았지 많은 공식 문서를 직접 읽지는 않았기 때문에 내부적으로 어떻게 작동하는지는 잘 모르니...

 

공부할게 어느곳이건 산더미군... ㅠㅠ

 

비록 베낀 글이지만 이런것도 잇구나 하는 것에 의의를 둔다.