원문: https://react.dev/blog/2024/04/25/react-19-upgrade-guide
리액트 19에 추가된 개선 사항들은 일부 호환성이 깨지는 변경사항이 동반되지만, 최대한 원활한 업그레이드가 되도록 노력했으며 대부분의 앱에는 영향을 미치지 않을 것으로 예상됩니다.
리액트 18.3이 배포되었습니다.
리액트 19로의 업그레이드를 더 쉽게 하기 위해, 18.2와 동일하지만 지원 중단 예정인 API에 대한 경고와 리액트 19를 사용하기 위해 필요한 변경사항들이 추가된 react@18.3
버전을 배포했습니다.
리액트 19로 업그레이드하기 전에 먼저 리액트 18.3으로 업그레이드하여 잠재적인 문제를 파악하시기를 권장합니다.
18.3의 변경사항 목록은 릴리스 노트를 참조하세요.
이 글에서는 리액트 19로 업그레이드하는 방법을 안내해드립니다.
리액트 19를 테스트하는 데 도움을 주고 싶으시다면, 이 업그레이드 가이드의 단계들을 따라 진행하시고 발견하신 문제점들을 보고해주세요. 리액트 19에 추가된 새로운 기능들의 목록은 리액트 19 릴리즈 포스트를 참조하세요.
새로운 JSX 변환은 이제 필수입니다
2020년에 번들 크기를 개선하고 리액트를 import하지 않고도 JSX를 사용할 수 있도록 새로운 JSX 변환(Transform)을 도입했습니다. 리액트 19의 ref를 prop으로 사용하는 것, JSX 속도 개선과 같은 추가적인 개선사항들은 새로운 변환을 필요로 합니다.
새로운 변환이 활성화되어 있지 않다면, 다음과 같은 경고가 표시될 것입니다.
앱(또는 의존성 중 하나)이 구버전 JSX 변환을 사용하고 있습니다. 더 빠른 성능을 위해 최신 JSX 변환으로 업데이트하세요: https://react.dev/link/new-jsx-transform
대부분의 환경에서 이미 변환이 활성화되어 있기 때문에 대부분의 앱은 영향을 받지 않을 것으로 예상됩니다. 수동으로 업그레이드하는 방법에 대한 안내는 공지 글을 참조해 주세요.
최신 버전의 리액트와 리액트 DOM을 설치하기 위해 다음 작업을 진행해주세요.
npm install --save-exact react@^19.0.0 react-dom@^19.0.0
Yarn을 사용하고 있다면 다음을 진행해주세요.
yarn add --exact react@^19.0.0 react-dom@^19.0.0
타입스크립트를 사용한다면 타입도 업데이트 해야합니다.
npm install --save-exact @types/react@^19.0.0 @types/react-dom@^19.0.0
Yarn을 사용한다면 아래와 같이 진행해주세요.
yarn add --exact @types/react@^19.0.0 @types/react-dom@^19.0.0
일반적으로 필요한 변환을 지원하기 위한 codemod도 포함하고 있습니다. 아래의 타입스크립트 변경사항을 참조하세요.
업그레이드를 돕기 위해, codemod.com 팀과 협력하여 리액트 19의 새로운 API와 패턴으로 코드를 자동으로 업데이트할 수 있는 codemod를 배포했습니다.
모든 codemod는 react-codemod
저장소에서 사용할 수 있으며, Codemod 팀이 codemod 유지보수를 돕기 위해 참여했습니다. 이 codemod를 실행하기 위해서는 react-codemod
대신 codemod
명령어를 사용하시는 것을 권장합니다. 더 빠르게 실행되고, 더 복잡한 코드 마이그레이션을 처리하며, 타입스크립트에 대한 더 나은 지원을 제공합니다.
모든 리액트 19 codemod 실행하기
리액트 19 codemod
레시피를 사용하면 이 가이드에 나열된 모든 codemod를 실행할 수 있습니다.
npx codemod@latest react/19/migration-recipe
이는 react-codemod
에서 다음의 codemod를 실행할 것입니다:
replace-reactdom-render
replace-string-ref
replace-act-import
replace-use-form-state
prop-types-typescript
이는 타입스크립트 변경사항을 포함하지 않습니다. 아래의 타입스크립트 변경사항을 참조하세요.
codemod가 포함되어 있는 변경사항들은 아래에 명령어가 포함되어 있습니다.
사용 가능한 모든 codemod의 목록은 react-codemod
저장소를 참조하세요.
이전 버전의 리액트에서는 렌더링 중에 발생한 에러를 잡아서 다시 발생시켰습니다. 개발 환경에서는 console.error
로도 기록하여 중복된 에러 로그가 발생했습니다.
리액트 19에서는 오류를 다시 발생시키지 않음으로써 중복을 줄이도록 에러 처리 방식을 개선했습니다.
window.reportError
에 보고됩니다.console.error
에 보고됩니다.이 변경사항은 대부분의 앱에 영향을 미치지 않을 것이지만, 만약 프로덕션 환경의 에러 리포팅이 에러가 다시 발생하는 것에 의존하고 있다면 에러 처리를 업데이트해야 할 수 있습니다. 이를 지원하기 위해 createRoot
와 hydrateRoot
에 사용자 정의 에러 처리를 위한 새로운 메소드를 추가했습니다.
const root = createRoot(container, {
onUncaughtError: (error, errorInfo) => {
// ... 에러 리포트 로그
},
onCaughtError: (error, errorInfo) => {
// ... 에러 리포트 로그
},
});
더 자세한 정보는 createRoot
와 hydrateRoot
의 문서를 참조하세요.
propTypes
와 defaultProps
PropTypes
는 2017년 4월(v15.5.0)에 지원 중단되었습니다.
리액트 19에서는 리액트 패키지에서 propType
검사를 제거했으며, 만약 사용했다면 조용히 무시될 것입니다. propTypes
를 사용하고 계신다면, 타입스크립트나 다른 타입 검사 솔루션으로 마이그레이션하시는 것을 권장합니다.
또한 함수 컴포넌트에서 defaultProps
대신 ES6 기본 매개변수를 사용하도록 변경했습니다. 클래스 컴포넌트는 ES6 대안이 없기 때문에 계속해서 defaultProps
를 지원할 것입니다.
// 이전
import PropTypes from "prop-types";
function Heading({ text }) {
return <h1>{text}</h1>;
}
Heading.propTypes = {
text: PropTypes.string,
};
Heading.defaultProps = {
text: "Hello, world!",
};
// 이후
interface Props {
text?: string;
}
function Heading({ text = "Hello, world!" }: Props) {
return <h1>{text}</h1>;
}
propTypes
를 타입스크립트로 변경하는 Codemod
npx codemod@latest react/prop-types-typescript
contextTypes
와 getChildContext
를 사용하는 레거시 Context레거시 Context는 2018년 10월(v16.6.0)에 지원 중단되었습니다.
레거시 Context는 contextTypes
와 getChildContext
API를 사용하는 클래스 컴포넌트에서만 사용 가능했으며, 놓치기 쉬운 미묘한 버그들 때문에 contextType
으로 대체되었습니다. 리액트 19에서는 리액트를 조금 더 작고 빠르게 만들기 위해 레거시 Context를 제거했습니다.
아직 클래스 컴포넌트에서 레거시 Context를 사용하고 계신다면, 새로운 contextType
API로 마이그레이션해야 합니다.
// 이전
import PropTypes from "prop-types";
class Parent extends React.Component {
static childContextTypes = {
foo: PropTypes.string.isRequired,
};
getChildContext() {
return { foo: "bar" };
}
render() {
return <Child />;
}
}
class Child extends React.Component {
static contextTypes = {
foo: PropTypes.string.isRequired,
};
render() {
return <div>{this.context.foo}</div>;
}
}
// 이후
const FooContext = React.createContext();
class Parent extends React.Component {
render() {
return (
<FooContext value="bar">
<Child />
</FooContext>
);
}
}
class Child extends React.Component {
static contextType = FooContext;
render() {
return <div>{this.context}</div>;
}
}
문자열 ref는 2018년 3월(v16.3.0)에 지원 중단되었습니다.
클래스 컴포넌트는 여러 이슈들 때문에 ref 콜백으로 대체되기 전까지 문자열 ref를 지원했습니다. 리액트 19에서는 리액트를 더 단순하고 이해하기 쉽게 만들기 위해 문자열 ref를 제거했습니다.
아직 클래스 컴포넌트에서 문자열 ref를 사용하고 계신다면, ref 콜백으로 마이그레이션해야 합니다.
// 이전
class MyComponent extends React.Component {
componentDidMount() {
this.refs.input.focus();
}
render() {
return <input ref="input" />;
}
}
// 이후
class MyComponent extends React.Component {
componentDidMount() {
this.input.focus();
}
render() {
return <input ref={(input) => (this.input = input)} />;
}
}
문자열 ref를 ref
callback으로 변경하는 Codemod
npx codemod@latest react/19/replace-string-ref
모듈 패턴 팩토리는 2019년 8월(v16.9.0)에 지원 중단되었습니다.
이 패턴을 지원하는 것은 리액트를 필요 이상으로 크고 느리게 만들었지만 사용률은 아주 낮았습니다. 리액트 19에서는 모듈 패턴 팩토리에 대한 지원을 제거했으며, 일반 함수로 마이그레이션해야 합니다.
// 이전
function FactoryComponent() {
return {
render() {
return <div />;
},
};
}
// 이후
function FactoryComponent() {
return <div />;
}
React.createFactory
createFactory
는 2020년 2월(v16.13.0)에 지원 중단되었습니다.
createFactory
사용은 JSX가 널리 지원되기 전에 일반적이었지만, 오늘날에는 거의 사용되지 않으며 JSX로 대체할 수 있습니다. 리액트 19에서는 createFactory
를 제거했으며 사용하고 있다면 JSX로 마이그레이션해야 합니다.
// 이전
import { createFactory } from "react";
const button = createFactory("button");
// 이후
const button = <button />;
react-test-renderer/shallow
리액트 18에서는 react-shallow-renderer를 다시 내보내도록 react-test-renderer/shallow
를 업데이트했습니다. 리액트 19에서는 react-test-renderer/shallow
를 제거하며 패키지를 직접 설치하는 것을 지향합니다.
npm install react-shallow-renderer --save-dev
- import ShallowRenderer from 'react-test-renderer/shallow';
+ import ShallowRenderer from 'react-shallow-renderer';
Shallow rendering은 리액트 내부 동작에 의존하기 때문에 향후 업그레이드를 방해할 수 있습니다. 테스트를 @testing-library/react 또는 @testing-library/react-native로 마이그레이션하시는 것을 권장합니다.
react-dom/test-utils
act
를 react-dom/test-utils
에서 제거하고 react
패키지로 옮겼습니다.
ReactDOMTestUtils.act
는 더 이상 사용되지 않고React.act
를 사용하는 것을 권장합니다.react-dom/test-utils
대신react
에서act
를 import 하세요. 자세한 내용은 https://react.dev/warnings/react-dom-test-utils 을 참조하세요.
위 경고를 해결하기 위해서는 act
를 react
에서 import해야 합니다.
- import {act} from 'react-dom/test-utils'
+ import {act} from 'react';
다른 모든 test-utils
함수들은 제거되었습니다. 이러한 유틸리티들은 일반적으로 잘 사용되지 않았고, 컴포넌트와 리액트의 낮은 수준의 구현 세부사항에 너무 쉽게 의존하게 만들었습니다. 리액트 19에서는 이러한 함수들을 호출할 때 에러가 발생할 것이며, 이후 버전에서는 이러한 내보내기(exports)들이 완전히 제거될 예정입니다.
대안으로 해당 경고 페이지를 참고해주세요.
ReactDOMTestUtils.act
를 React.act
로 변환하는 Codemod
npx codemod@latest react/19/replace-act-import
ReactDOM.render
ReactDOM.render
는 2022년 3월(v18.0.0)에 지원 중단되었습니다. 리액트 19에서는 ReactDOM.render
가 제거되므로 ReactDOM.createRoot
로 마이그레이션해야 합니다.
// 이전
import { render } from "react-dom";
render(<App />, document.getElementById("root"));
// 이후
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
root.render(<App />);
ReactDOM.render
를 ReactDOMClient.createRoot
로 변환하는 Codemod
npx codemod@latest react/19/replace-reactdom-render
ReactDOM.hydrate
ReactDOM.hydrate
는 2022년 3월(v18.0.0)에 지원 중단되었습니다. 리액트 19에서는 ReactDOM.hydrate
가 제거되므로 ReactDOM.hydrateRoot
로 마이그레이션해야 합니다.
// 이전
import { hydrate } from "react-dom";
hydrate(<App />, document.getElementById("root"));
// 이후
import { hydrateRoot } from "react-dom/client";
hydrateRoot(document.getElementById("root"), <App />);
ReactDOM.hydrate
를 ReactDOMClient.hydrateRoot
로 변환하는 Codemod
npx codemod@latest react/19/replace-reactdom-render
unmountComponentAtNode
ReactDOM.unmountComponentAtNode
는 2022년 3월(v18.0.0)에 지원 중단되었습니다. 리액트 19에서는 root.unmount()
로 마이그레이션해야 합니다.
// 이전
unmountComponentAtNode(document.getElementById("root"));
// 이후
root.unmount();
root.unmount()
에 대해 더 많은 정보를 알고 싶으시다면 createRoot
와 hydrateRoot
를 참고하세요.
unmountComponentAtNode
를 root.unmount
로 변환하는 Codemod
npx codemod@latest react/19/replace-reactdom-render
ReactDOM.findDOMNode
ReactDOM.findDOMNode
는 2018년 10월(v16.6.0)에 지원 중단되었습니다.
findDOMNode
는 실행이 느리고, 리팩토링에 취약하며, 첫 번째 자식만 반환하고, 추상화 레벨을 깨뜨리는 오래된 임시방편이였기 때문에 제거하기로 했습니다(자세히 보기). ReactDOM.findDOMNode
는 DOM refs로 대체할 수 있습니다.
// 이전
import { findDOMNode } from "react-dom";
function AutoselectingInput() {
useEffect(() => {
const input = findDOMNode(this);
input.select();
}, []);
return <input defaultValue="Hello" />;
}
// 이후
function AutoselectingInput() {
const ref = useRef(null);
useEffect(() => {
ref.current.select();
}, []);
return <input ref={ref} defaultValue="Hello" />;
}
element.ref
리액트 19는 ref
를 prop으로서 제공하기 때문에 element.ref
를 지원 중단하고 element.props.ref
를 사용할 것을 권장합니다.
element.ref
에 접근하면 아래와 같은 경고가 발생합니다.
element.ref에 접근하는 것은 더 이상 지원하지 않습니다. ref는 이제 일반적인 prop으로 사용할 수 있습니다. 따라서 추후 릴리즈에서 JSX 엘리먼트 타입에서 제거될 예정입니다.
react-test-renderer
저희는 react-test-renderer
를 더 이상 사용하지 않기로 했습니다. 이는 사용자들이 사용하는 환경과 일치하지 않는 자체 렌더러 환경을 구현하고, 구현 세부사항 테스트를 조장하며, 리액트 내부에 의존하기 때문입니다.
이 테스트 렌더러는 React Testing Library와 같은 더 유용한 테스트 전략들이 있기 전에 만들어졌으며, 이제는 이러한 현대적인 테스트 라이브러리를 사용할 것을 권장합니다.
리액트 19에서는 react-test-renderer
에서 지원 중단 경고가 표시되고, 동시성 렌더링을 하도록 전환되었습니다. 현대적이고 더욱 잘 지원되는 테스트 경험을 위해 여러분의 테스트를 @testing-library/react 또는 @testing-library/react-native로 마이그레이션할 것을 권장합니다.
리액트 19에서는 Strict Mode에 여러 개선사항과 수정사항이 포함되었습니다.
개발 환경에서 Strict Mode로 인한 이중 렌더링이 발생할 때, useMemo
와 useCallback
은 두 번째 렌더링에서 첫 번째 렌더링의 메모이제이션된 결과를 재사용하게 됩니다. 컴포넌트들이 이미 Strict Mode와 호환된다면 동작에 있어 특별한 차이를 느끼지 못할 것입니다.
다른 Strict Mode의 기능들과 마찬가지로, 이러한 특징들은 개발 단계에서 컴포넌트의 잠재적인 버그를 미리 발견하고 프로덕션 배포 전에 수정할 수 있도록 설계되었습니다. 예를 들어, 개발 환경에서 Strict Mode는 초기 마운트 시 ref 콜백 함수를 두 번 호출하는데, 이는 마운트된 컴포넌트가 Suspense fallback으로 대체될 때 발생할 수 있는 상황을 시뮬레이션하기 위한 것입니다.
리액트 19에서는 컴포넌트가 suspense 상태가 되면, 리액트는 형제 트리 전체의 렌더링이 완료되기를 기다리지 않고 즉시 가장 가까운 Suspense 경계의 fallback을 표시합니다. fallback이 적용된 후에는, 리액트는 트리의 나머지 부분에서 지연 로딩되는 요청들을 미리 준비하기 위해 일시 중단된 형제 컴포넌트들의 렌더링을 다시 스케줄링합니다.
이전 버전에서는 컴포넌트가 suspense 상태가 되면, 일시 중단된 형제 컴포넌트들이 먼저 렌더링된 후에 fallback UI가 적용되었습니다.
리액트 19에서는 컴포넌트가 suspense 상태가 되면, 먼저 fallback UI가 적용되고 그 후에 일시 중단된 형제 컴포넌트들이 렌더링됩니다.
이는 Suspense fallback UI를 더 빠르게 표시하면서도, 백그라운드에서는 실제 컨텐츠를 위한 데이터나 리소스를 계속해서 준비할 수 있도록 합니다.
과거에는 리액트를 빌드 과정 없이 간편하게 로드하기 위해 UMD(Universal Module Definition) 방식이 널리 사용되었습니다. 하지만 이제는 HTML 문서에서 모듈을 스크립트로 로드하는 더 현대적인 방법들이 등장했습니다. 이에 따라 리액트 팀은 테스트와 배포 프로세스를 단순화하기 위해 리액트 19부터는 UMD 빌드 제공을 중단하기로 결정했습니다.
script 태그로 리액트 19를 로드하려면 esm.sh와 같은 ESM(ECMAScript Module) 기반의 CDN을 사용하는 것을 권장합니다.
<script type="module">
import React from "https://esm.sh/react@19/?dev"
import ReactDOMClient from "https://esm.sh/react-dom@19/client?dev"
...
</script>
이번 릴리스에는 리액트 내부의 변경사항이 포함되어 있습니다. 이는 우리가 '절대 사용하지 말라'고 경고했던 SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
와 같은 내부 기능을 무시하고 사용한 라이브러리들에 영향을 미칠 수 있습니다. 이러한 변경은 리액트 19의 개선사항을 적용하기 위해 필요한 것이며, 가이드라인을 준수한 라이브러리들에는 영향을 주지 않습니다.
우리의 버전 관리 정책에 따르면, 이러한 업데이트들은 주요 변경사항(breaking changes)으로 분류되지 않으며, 업그레이드 방법에 대한 문서도 제공하지 않을 것입니다. 내부 기능에 의존하는 모든 코드를 제거할 것을 권장합니다.
내부 기능 사용이 미치는 영향을 더 명확히 전달하기 위해, SECRET_INTERNALS
접미사를 다음과 같이 변경했습니다.
_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE
앞으로는 사용을 더욱 강력히 제한하고 사용자들의 업그레이드가 방해받지 않도록 하기 위해, 리액트의 내부 기능 접근을 더 적극적으로 차단할 예정입니다.
리액트 19에서 제거된 API들을 기반으로 타입스크립트 타입들을 정리했습니다. 일부 제거된 타입들은 더 관련성 있는 패키지로 이동되었고, 일부는 리액트의 동작을 설명하는 데 더 이상 필요하지 않게 되었습니다.
참고
대부분의 타입 관련 주요 변경사항을 쉽게 마이그레이션하기 위해 types-react-codemod
를 배포했습니다.
npx types-react-codemod@latest preset-19 ./path-to-app
만약 element.props
에 대한 불안정한 접근이 많다면, 다음과 같은 추가 codemod를 실행해보세요.
npx types-react-codemod@latest react-element-default-any-props ./path-to-your-react-ts-files
지원되는 대체 목록은 types-react-codemod
를 확인하세요. Codemod가 누락된 부분이 있다면 리액트 19 누락된 codemod 목록에서 확인할 수 있습니다.
ref
정리 필수이 변경사항은 react-19
codemod 프리셋의 no-implicit-ref-callback-return
에 포함되어 있습니다.
ref 정리 함수의 도입으로 인해, ref 콜백에서 다른 것을 반환하는 것은 이제 타입스크립트에서 거부됩니다. 일반적으로 암묵적 반환을 사용하지 않도록 수정하면 됩니다.
- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />
원래 코드는 HTMLDivElement
의 인스턴스를 반환했고 타입스크립트는 이것이 정리 함수인지 아닌지 알 수 없었습니다.
useRef
는 인자가 필요합니다이 변경사항은 react-19
codemod 프리셋의 refobject-defaults
에 포함되어 있습니다.
타입스크립트와 리액트가 작동하는 방식에 대한 오랜 불만 중 하나가 useRef
였습니다. 이제 useRef
가 인자를 필요로 하도록 타입을 변경했습니다. 이는 타입 시그니처를 크게 단순화합니다. 이제 createContext
와 더 비슷하게 동작할 것입니다.
// @ts-expect-error: 인자가 1개 필요하지만 없음
useRef();
// 통과
useRef(undefined);
// @ts-expect-error: 인자가 1개 필요하지만 없음
createContext();
// 통과
createContext(undefined);
이는 이제 모든 ref가 변경 가능함을 의미하기도 합니다. null
로 초기화했기 때문에 ref를 변경할 수 없는 문제가 더 이상 발생하지 않습니다.
const ref = useRef<number>(null);
// 'current'는 읽기 전용 속성이므로 할당할 수 없음
ref.current = 1;
MutableRef
는 이제 useRef
가 항상 반환할 단일 RefObject
타입을 위해 더 이상 사용되지 않습니다.
interface RefObject<T> {
current: T
}
declare function useRef<T>: RefObject<T>
useRef
는 여전히 useRef<T>(null)
에 대해 자동으로 RefObject<T | null>
을 반환하는 오버로드를 가지고 있습니다. useRef
의 필수 인자로 인한 마이그레이션을 쉽게 하기 위해, 자동으로 RefObject<T | undefined>
를 반환하는 useRef(undefined)
에 대한 오버로드가 추가되었습니다.
이 변경사항에 대한 이전 논의는 [RFC] Make all refs mutable을 참조하세요.
ReactElement
타입스크립트 타입의 변경사항이 변경사항은 react-element-default-any-props
codemod에 포함되어 있습니다.
리액트 엘리먼트의 props
는 이제 ReactElement
로 타입이 지정된 경우 기본값이 any
대신 unknown
으로 설정됩니다. ReactElement
에 타입 인자를 전달했다면 영향을 주지 않습니다.
type Example2 = ReactElement<{ id: string }>["props"];
// ^? { id: string }
만약 타입 인자 전달 없이 기본값을 사용했다면, 이제 unknown
을 처리해야 합니다.
type Example = ReactElement["props"];
// ^? 이전에는 'any'였으나, 이제는 'unknown'
이는 엘리먼트 props에 대한 타입 체크를 우회하거나 무시하며 접근하는 레거시 코드가 많은 경우에만 필요합니다. 엘리먼트 검사(Element introspection)는 일종의 우회로서 존재하며, 명시적으로 any
를 사용함으로써 props 접근이 안전하지 않다는 것을 명확히 표현해야 합니다.
이 변경사항은 react-19
codemod 프리셋의 scoped-jsx
에 포함되어 있습니다.
오랫동안 요청되어 온 변경사항으로, 전역 JSX
네임스페이스를 React.JSX
로 대체했습니다. 이를 통해 JSX를 활용하는 다른 UI 라이브러리들 간의 충돌을 방지하고 전역 타입의 오염을 막을 수 있습니다.
이제 JSX 네임스페이스의 모듈 확장을 declare module "…"
로 감싸야 합니다.
// global.d.ts
+ declare module "react" {
namespace JSX {
interface IntrinsicElements {
"my-element": {
myElementProps: string;
};
}
}
+ }
정확한 모듈 지정자는 tsconfig.json
의 compilerOptions
에서 지정한 JSX 런타임에 따라 다릅니다.
"jsx": "react-jsx"
의 경우 react/jsx-runtime
"jsx": "react-jsxdev"
의 경우 react/jsx-dev-runtime
"jsx": "react"
및 "jsx": "preserve"
의 경우 react
useReducer
타입@mfp22
덕분에 useReducer
는 이제 더 나은 타입 추론을 제공합니다.
하지만 이로 인해 useReducer
가 전체 리듀서 타입을 타입 매개변수로 받지 않고, 컨텍스트 타입 추론에 의존하거나 상태와 액션 타입을 모두 필요로 하는 breaking change가 발생했습니다.
가장 좋은 방법은 useReducer
에 타입 인자를 전달하지 않는 것입니다.
- useReducer<React.Reducer<State, Action>>(reducer)
+ useReducer(reducer);
상태와 액션의 타입을 명시적으로 지정할 수 있는 엣지 케이스의 경우, Action
을 튜플로 전달할 수 있습니다.
- useReducer<React.Reducer<State, Action>>(reducer)
+ useReducer<State, [Action]>(reducer);
reducer를 인라인으로 정의하는 경우, 함수 매개변수에 타입을 추가하는 것을 권장합니다.
- useReducer<React.Reducer<State, Action>>((state, action) => state)
+ useReducer((state: State, action: Action) => state)
reducer를 useReducer
호출 밖으로 이동하는 경우에도 동일하게 적용됩니다.
const reducer = (state: State, action: Action) => state;
src
와 href
에서 자바스크립트 URL에 대한 에러 처리 #26507onRecoverableError
에서 errorInfo.digest
제거 #28222unstable_flushControlled
제거 #26397unstable_createEventHandle
제거 #28271unstable_renderSubtreeIntoContainer
제거 #28271unstable_runWithPriority
제거 #28271react-is
에서 더 이상 사용되지 않는 메서드 제거 #28224전체 변경사항은 Changelog를 참조하세요.