인강을 따라가던 중
create-react-app 설치로 만들어진 bolier plate를 살펴보니
강사님의 것과 내 것이 서로 다르게 만들어진 것을 확인했다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
ReactDOM.render( // <-----------------
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root') // <-----------------
);
☝️강사님의 index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root')); // <-----------------
root.render( // <-----------------
<React.StrictMode>
<App />
</React.StrictMode>
);
☝️내 index.js
ReactDOM 이후에 오는 메소드에 차이가 있는 것 같다.
쓱 보고 강사님 버전으로 내걸 수정해봤는데 음…. 제대로 동작하지 않는다.
어떤 차이가 있는걸까?? 두 차이를 이해하기 위해서 구글링 해보자
root API의 변화
// Legacy root API
ReactDOM.render(<App/>, document.getElementById("root"))
// New root API
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(<App/>)
강사님의 버전을 Legacy root API, 내 버전을 New root API 라고 나눌 수 있다.
Legacy root API
ReactDOM 객체에서 render() 메소드를 호출한다.
첫 번째 매개변수로는 렌더링한 React 컴포넌트(APP)를, 두 번째 매개변수로는 컴포넌트를 렌더링한 실제 DOM 요소(container)를 지정하는 형태다.
import * as ReactDOM from 'react-dom';
import App from 'App';
const container = document.getElementById('app');
// Initial render.
ReactDOM.render(<App tab="home" />, container);
// During an update, React would access
// the root of the DOM element.
ReactDOM.render(<App tab="profile" />, container);
주요 차이는 업데이트(렌더링)의 방식.
state나 props 변화가 있을 때, 변수 container가 변경되지 않더라도 계속 렌더링할 때마다 container를 전달하는 형태라고 한다.
New root API
New root API는 React18에서 도입된 새로운 렌더링 API 이다.
ReactDOM.createRoot() 메서드를 사용하여 루트 렌더러(root renderer)를 생성한다.
이 루트 렌더러는 render() 메서드를 사용하여 컴포넌트를 렌더링한다.
import * as ReactDOM from 'react-dom';
import App from 'App';
const container = document.getElementById('app');
// Create a root.
const root = ReactDOM.createRoot(container);
// Initial render: Render an element to the root.
root.render(<App tab="home" />);
// During an update, there's no need to pass the container again.
root.render(<App tab="profile" />);
데이터 구조의 최상위 레벨에 있는 container를 매번 전달하지 않아도 되는 형태라고 한다.
필요에 따라 업데이트를 할 수 있다는게 regacy root api와의 가장 큰 차이점이다.
그리고 React18에서 새로 도입된 서버 컴포넌트(Server Components)와 같은 새로운 기능을 사용하기 위해서는 꼭 사용해야 한다고 한다.
Legacy root API 사용 시 오류 메세지
위에서 언급했듯이 나 같은 경우는 Legacy root API 형식으로 index.js를 수정하니 제대로 실행되지 않았다.
오류메세지는 아래와 같다.
Uncaught TypeError: react_dom_client__WEBPACK_IMPORTED_MODULE_1__.render is not a function at ./src/index.js (index.js:8:1)
오류 메세지가 발생한 index.js의 8번째 줄은 "ReactDOM.render" 가 작성되어 있었다.
React18 에서 위 방식은 더 이상 지원하지 않는다고 한다. 레거시라고 하더니 진짜 레거시…… 바로 안써버리게 된 것
package.json을 확인해보니 내 리액트는 18버전이 맞았다.
{
...
"dependencies": {
...
"react": "^18.2.0",
"react-dom": "^18.2.0"
...
Legacy root API를 사용하고 싶다면?
사용 할 수 있는 방법은 간단하다.
React18에서만 가능하다고? 다운그레이드하면 된다.
React17 이하로 다운그레이드 시키면 이전 문법 사용하도록 허용한다.
$ npm install react@^17.0.2
하지만 새로운 프로젝트를 진행하는 것이라면 얌전히 최신버전인 React18을 사용하며 변화를 받아들이는게 좋지 않을까 싶다.
나는 최대한 React18 과 new root API 를 이용할 것 같다.
비고
https://bobbyhadz.com/blog/react-reacdom-render-no-longer-supported-in-react-18
https://avocado12-note.tistory.com/41
'REACT' 카테고리의 다른 글
[REACT] React Hooks 탐구하기 (0) | 2023.10.15 |
---|---|
[REACT] createGlobalStyle 안에서 @import 사용 경고 해결하기 (0) | 2023.10.01 |
[REACT] TDD 와 리액트 테스트 도구 (0) | 2023.09.15 |
[REACT] DOM과 Virtual DOM (0) | 2023.04.12 |
[REACT] 두 번 렌더링되는 현상? (unmount가 중복 실행되는 현상) (react strict) (0) | 2023.03.07 |