리액트 18이 나온것은 알고있었다. 하지만 그건 찬찬히 공부하기로 하고 지금 하고 있던
프로젝트를 켰는데 콘솔창에 이런 에러문구가 나오더라.
react-dom.development.js:86 Warning: ReactDOM.render is
no longer supported in React 18. Use createRoot instead.
Until you switch to the new API, your app will behave as
if it's running React 17
번역하자면
react-dom.development.js:86 경고: ReactDOM.render는 React 18 에서
더 이상 지원되지 않습니다. 대신 createRoot를 사용하십시오. 새 API로 전환할
때까지 앱은 React 17을 실행하는 것처럼 작동합니다.
라는 내용이다. 가만있어보자, ReactDOM.render 라면....
index.ts 파일에서 App.ts 를 html 로 렌더해주는 녀석 아닌가?
그래서 확인해봤다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render( // <- 이부분
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
여기다. 그렇다면 저 문구의 뜻대로라면.. 이제 저 ReactDOM.render 는 리액트 18에선
더이상 지원되지 않으니 createRoot 를 사용하라는 것이군... 오케이 확인
그렇다면 저 문구를 계속 보기 싫으니 createRoot 를 사용해주겠다.
일단 현재 프로젝트의 package.json 을 확인해보자.
"dependencies": {
"@testing-library/jest-dom": "^5.16.3",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.4.1",
"@types/node": "^16.11.26",
"@types/react": "^17.0.43",
"@types/react-dom": "^17.0.14",
"react": "^18.1.0-next-af730436c-20220405",
"react-dom": "^18.1.0-next-af730436c-20220405",
"react-scripts": "5.0.0",
"typescript": "^4.6.3",
"web-vitals": "^2.1.4"
},
현재 내 react 버전은 18버전이 되어있다. 만약 17버전을 가지고 있다면 업데이트를 해주자
yarn add react@next react-dom@next
그렇게 18버전이 되었다면 index.ts 로 넘어가서 아까의 코드를 수정해주자.
Before
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
After
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>
);
잘 되는가? 아마 오류가 날것이다. 만약 이 프로젝트가 자바스크립트였다면 정상적으로
작동했겠지만, 우리는 타입스크립트를 사용하기때문에 오류가 발생했다.
아마
Property 'createRoot' does not exist on type 'typeof
import("/code/my-app/node_modules/@types/react-dom/index")'. TS2339
이런 오류일것이다. 타입유형에 createRoot 라는 속성이 없다는것이다.
현재 프로젝트에는 해당 API가 정의되어있지 않기 때문이다.
그렇다면 이제 그 유형을 업그레이드 해보자.
yarn add @types/react @types/react-dom
자, 이제 된거같지만 여전히 오류가 발생한다. 이쯤에서 살짝 올라오지만 잘 참고 끝까지
해보자.
선언한 타입을 실제프로젝트에 로드해야되는데 하나의 과정이 남아있다.
tsconfig.json 의 compilerOption 에 react/next 를 추가하는것이다.
"types": ["react/next", "react-dom/next"]
이런식으로 추가해주자.
그럼 드디어 된건가???? 놉. 여전히 오류가 난다.하지만 좀 다른 오류가 나왔다.
Argument of type 'HTMLElement | null' is not assignable to
parameter of type 'Element | DocumentFragment'.
Type 'null' is not assignable to type 'Element | DocumentFragment'.
형식 인수 ''Element | DocumentFragment' 형식의 매개 변수에
HTMElement | null'을(를) 할당할 수 없습니다.
'null' 유형은 'Element | DocumentFragment' 유형에 할당할 수 없습니다.
이 오류는 타입스크립트에서 null 을 반환할 수 없다는 뜻인데, 이 부분을 손봐주면 된다.
import React from 'react';
import ReactDOM from "react-dom/client";
import './index.css';
import App from './App';
const rootElement = document.getElementById('root');
if (!rootElement) throw new Error('Failed to find the root element');
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
rootElement 가 null 일 경우의 조건문을 만들어 에러처리시키면 정상적으로 동작한다.
이렇게 타입스크립트에 리액트18을 얹는 과정이 끝났다. 계속 적응해봅시다.
참고사이트
https://blog.logrocket.com/how-to-use-typescript-with-react-18-alpha/
감사합니다