diff --git a/src/content/blog/2024/04/01/react-19-upgrade-guide.md b/src/content/blog/2024/04/01/react-19-upgrade-guide.md index 7f891a4cd..cdff6dd9f 100644 --- a/src/content/blog/2024/04/01/react-19-upgrade-guide.md +++ b/src/content/blog/2024/04/01/react-19-upgrade-guide.md @@ -14,6 +14,8 @@ If you'd like to help us test React 19, follow the steps in this upgrade guide a + + React Conf 2024 is scheduled for May 15–16 in Henderson, Nevada! @@ -36,52 +38,243 @@ Or if you’re using yarn: ```bash yarn add react react-dom ``` + +#### New JSX Transform is now required {/*new-jsx-transform-is-now-required*/} -TODO: Note about jsx transform? +We introduced a [new JSX transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) in 2020 to improve bundle size and use JSX without importing React. In React 19, we're adding additional improvements like using ref as a prop and JSX speed improvements that require the new transform. -## New JSX Transform {/*new-jsx-transform*/} +If you haven't already, you will need to enable the new transform in your project. We expect most apps will not be effected since the transform is enabled in most environments already. For manual instructions on how to upgrade, please see the [announcement post](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html). -TODO: new jsx transform now required + + +## Removing deprecated React APIs {/*removing-deprecated-react-apis*/} + +### Removing PropTypes and DefaultProps {/*removing-proptypes-and-defaultprops*/} +`PropTypes` were been [deprecated in v15.5.0](https://legacy.reactjs.org/blog/2017/04/07/react-v15.5.0.html#new-deprecation-warnings). + +In React 19, we're removing the PropType checks from the React package, and using them will be silently ignored. If you're using PropTypes, we recommend migrating to TypeScript or another type-checking solution. We're also removing `defaultProps` in place of ES6 default parameters. + +```js +// Before +import PropTypes from 'prop-types'; + +function Heading({text}) { + return

{text}

; +} +Heading.propTypes = { + text: PropTypes.string, +}; +Heading.defaultProps = { + text: 'Hello, world!', +}; +``` +```ts +// After +interface Props { + text?: string; +} +function Heading({text = 'Hello, world!'}: Props) { + return

{text}

; +} +``` + +### Removing Legacy Context {/*removing-legacy-context*/} + +Legacy Context using `contextTypes` and `getChildContext` was [deprecated in v16.6.0](https://legacy.reactjs.org/blog/2018/10/23/react-v-16-6.html) due to subtle bugs that were easy to miss. In React 19, we're removing Legacy Context to make React slightly smaller and faster. + +If you're still using Legacy Context in class components, you'll need to migrate to the new `contextType` API: + +```js +// Before +import PropTypes from 'prop-types'; + +class Parent extends React.Component { + static childContextTypes = { + foo: PropTypes.string.isRequired, + }; + + getChildContext() { + return { foo: 'bar' }; + } + + render() { + return ; + } +} + +class Child extends React.Component { + static contextTypes = { + foo: PropTypes.string.isRequired, + }; + + render() { + return
{this.context.foo}
; + } +} +``` + +```js +// After +const FooContext = React.createContext(); + +class Parent extends React.Component { + render() { + return ( + + + + ); + } +} + +class Child extends React.Component { + static contextType = FooContext; + + render() { + return
{this.context}
; + } +} +``` + +### Removing string refs {/*removing-string-refs*/} +String refs were [deprecated in v16.3.0](https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html) because they had [multiple downsides](https://github.com/facebook/react/issues/1373). In React 19, we're removing string refs to make React simpler and easier to understand. + +If you're still using string refs in class components, you'll need to migrate to ref callbacks: + +```js +// Before +class MyComponent extends React.Component { + componentDidMount() { + this.refs['input'].focus(); + } + + render() { + return ; + } +} +``` + +```js +// After +// Before +class MyComponent extends React.Component { + componentDidMount() { + this.input.focus(); + } + + render() { + return this.input = input} />; + } +} +``` + + + +To help with the migration, we've created a [react-codemod](/todo) that will automatically update your code to use ref callbacks. + +TODO: instructions. + + + +### Removing module pattern factories {/*removing-module-pattern-factories*/} +Module pattern factories were [deprecated in v16.9.0](https://legacy.reactjs.org/blog/2019/08/08/react-v16.9.0.html#deprecating-module-pattern-factories) because they were rarely used and supporting it causes React to be slightly larger and slower than necessary. In React 19, we're removing support for module pattern factories, and you'll need to migrate to regular functions: + +```js +// Before +function FactoryComponent() { + return { render() { return
; } } +} +``` + +```js +// After +function FactoryComponent() { + return
; +} +``` + +### Removing `createFactory` {/*removing-createfactory*/} +`createFactory` was [deprecated in v16.13.0](https://legacy.reactjs.org/blog/2020/02/26/react-v16.13.0.html#deprecating-createfactory) because it was rarely used and is replaced by JSX. In React 19, we're removing `createFactory` and you'll need to migrate to JSX: + +```js +// Before +import { createFactory } from 'react'; + +const button = createFactory('button'); +``` + +```js +// After +const button =