React18 변경사항에 따라 ReactDOM.render > createRoot로 변경하기 (with TypeScript) | Type Assertion
React 18에서 더이상 지원하지 않는
ReactDom.render
대신createRoot
를 사용하기 위해 코드를 변경하는 과정, 그리고 TypeScript 타입 오류 해결을 위해 사용한Type assertion
에 대해 정리한 글입니다.
ReactDOM.render 오류
새로운 리액트 프로젝트를 CRA로 만들고 실행했더니 콘솔창에 처음보는 오류가 나타났다.
React 18버전에서는 ReactDom.render
를 더이상 지원하지 않으니 createRoot
를 대신 사용하라는 오류였다. 그래서 오류에 나와있는 react 문서 링크를 들어가보니 상세히 나와있었다.
// Before
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);
// After
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App tab="home" />);
위와 같은 예시코드를 보고 나의 코드도 변경하였다.
Before
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
After
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
const store = createStore(todoListReducer);
const container = document.getElementById("root");
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
❗️ TypeScript Issue
하지만 타입스크립트로 개발중이라면 위와 같이 작성했을 때 container
에 오류 문구가 표시된다.
container
에NULL
타입의 값은 할당할 수 없다는 오류이다.
💡 해결 방안
위의 상황처럼 실제로 값이 있다는 것을 알고있지만 Typescript의 타입 추론 결과에서는 null 값과 같은 알 수 없는 타입에 대한 정보가 나타날 경우 Type assertion(타입 단언)을 통해 타입을 지정해줄 수 있다.
Type Assertion
Type Assertion은 컴파일러에게 변수의 타입을 알려주는 메커니즘으로 TypeScript의 타입 추론 결과가 실제와 다르게 추론되었다 생각하는 경우 사용할 수 있다. 또한 Type Assertion은 컴파일러에 의해 제거되기 때문에 코드의 런타임 동작에 영향을 미치지 않는다.
* assertion : 컴퓨터 프로그래밍에서 어서션(영어: assertion)은 프로그램 안에 추가하는 참·거짓을 미리 가정하는 문으로 개발자는 해당 문이 그 문의 장소에서 언제나 참이라고 간주한다. (=표명, 가정 설정문)
1) as
Type Assertion은 컴파일러에게 변수의 타입을 알려주는 메커니즘으로 TypeScript의 타입 추론 결과가 실제와 다르게 추론되었다 생각하는 경우 사용할 수 있다. 또한 Type Assertion은 컴파일러에 의해 제거되기 때문에 코드의 런타임 동작에 영향을 미치지 않는다.
* assertion : 컴퓨터 프로그래밍에서 어서션(영어: assertion)은 프로그램 안에 추가하는 참·거짓을 미리 가정하는 문으로 개발자는 해당 문이 그 문의 장소에서 언제나 참이라고 간주한다. (=표명, 가정 설정문)
as
는 type assertion 구문 중 하나이며 아래와 같이 사용한다.
const container = document.getElementById("root") as HTMLElement;
2) angle bracket 구문
angle bracket 구문은 꺾쇠 괄호(<>
)로 HTML 태그의 모양과 같다.
const container = <HTMLElement>document.getElementById("root");
하지만 주의할 점이 있는데 angle brakcket은 HTML 태그와 형태가 동일하여 JSX 문법과 함께 사용할 수 없기 때문에 .jsx
나 .tsx
파일에서는 사용할 수 없다.
❗️위와 같은 방법을 통해서 타입을 단언해줄 수 있지만 Type Assertion은 개발자가 타입에 대해 확신할 수 있을 때만 사용하는 것이 좋다.❗️
참고로 알아둘 내용
위의 문제를 해결할 수 있는 다른 방법이 또 하나 있지만 이 방법은 권장하지 않는다.
Non-null assertion operator(Non-null 단언 연산자)
Non-null 단언 연산자는 변수 뒤에 느낌표(!
)를 붙여 나타내는 접미사 연산자로, 해당 값이 null, undefined 같은 값이 아니라고 단언해주는 역할을 한다. 하지만 eslint에서는 strict null-checking 모드의 이점을 무효화하기 때문에 사용을 허용하지 않는다고 한다.
const container = document.getElementById("root")!;
최종 코드
위의 해결 방안을 참고하여 최종적으로는 as
구문을 사용하여 해결하였다.
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
const store = createStore(todoListReducer);
const container = document.getElementById("root") as HTMLElement;
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
📖 참고 자료
react 문서 링크
Typescript 핸드북
Typescript-eslint 문서
Author And Source
이 문제에 관하여(React18 변경사항에 따라 ReactDOM.render > createRoot로 변경하기 (with TypeScript) | Type Assertion), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yeyo0x0/Type-Assertion저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)