diff --git a/src/content/blog/2024/04/25/react-19-upgrade-guide.md b/src/content/blog/2024/04/25/react-19-upgrade-guide.md deleted file mode 100644 index 53c051058..000000000 --- a/src/content/blog/2024/04/25/react-19-upgrade-guide.md +++ /dev/null @@ -1,741 +0,0 @@ ---- -title: "React 19 RC Upgrade Guide" -author: Ricky Hanlon -date: 2024/04/25 -description: The improvements added to React 19 require some breaking changes, but we've worked to make the upgrade as smooth as possible and we don't expect the changes to impact most apps. In this post, we will guide you through the steps for upgrading apps and libraries to React 19. ---- - -April 25, 2024 by [Ricky Hanlon](https://twitter.com/rickhanlonii) - ---- - - - - -The improvements added to React 19 RC require some breaking changes, but we've worked to make the upgrade as smooth as possible, and we don't expect the changes to impact most apps. - - - - - -#### React 18.3 has also been published {/*react-18-3*/} - -To help make the upgrade to React 19 easier, we've published a `react@18.3` release that is identical to 18.2 but adds warnings for deprecated APIs and other changes that are needed for React 19. - -We recommend upgrading to React 18.3 first to help identify any issues before upgrading to React 19. - -For a list of changes in 18.3 see the [Release Notes](https://github.com/facebook/react/blob/main/CHANGELOG.md). - - - -In this post, we will guide you through the steps for upgrading to React 19: - -- [Installing](#installing) -- [Codemods](#codemods) -- [Breaking changes](#breaking-changes) -- [New deprecations](#new-deprecations) -- [Notable changes](#notable-changes) -- [TypeScript changes](#typescript-changes) -- [Changelog](#changelog) - -If you'd like to help us test React 19, follow the steps in this upgrade guide and [report any issues](https://github.com/facebook/react/issues/new?assignees=&labels=React+19&projects=&template=19.md&title=%5BReact+19%5D) you encounter. For a list of new features added to React 19, see the [React 19 release post](/blog/2024/04/25/react-19). - ---- -## Installing {/*installing*/} - - - -#### New JSX Transform is now required {/*new-jsx-transform-is-now-required*/} - -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. - -If the new transform is not enabled, you will see this warning: - - - - - -Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance: https://react.dev/link/new-jsx-transform - - - - - - -We expect most apps will not be affected 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). - - - - -To install the latest version of React and React DOM: - -```bash -npm install --save-exact react@rc react-dom@rc -``` - -Or, if you're using Yarn: - -```bash -yarn add --exact react@rc react-dom@rc -``` - -If you're using TypeScript, you also need to update the types. Once React 19 is released as stable, you can install the types as usual from `@types/react` and `@types/react-dom`. Until the stable release, the types are available in different packages which need to be enforced in your `package.json`: - -```json -{ - "dependencies": { - "@types/react": "npm:types-react@rc", - "@types/react-dom": "npm:types-react-dom@rc" - }, - "overrides": { - "@types/react": "npm:types-react@rc", - "@types/react-dom": "npm:types-react-dom@rc" - } -} -``` - -We're also including a codemod for the most common replacements. See [TypeScript changes](#typescript-changes) below. - -## Codemods {/*codemods*/} - -To help with the upgrade, we've worked with the team at [codemod.com](https://codemod.com) to publish codemods that will automatically update your code to many of the new APIs and patterns in React 19. - -All codemods are available in the [`react-codemod` repo](https://github.com/reactjs/react-codemod) and the Codemod team have joined in helping maintain the codemods. To run these codemods, we recommend using the `codemod` command instead of the `react-codemod` because it runs faster, handles more complex code migrations, and provides better support for TypeScript. - - - - -#### Run all React 19 codemods {/*run-all-react-19-codemods*/} - -Run all codemods listed in this guide with the React 19 `codemod` recipe: - -```bash -npx codemod@latest react/19/migration-recipe -``` - -This will run the following codemods from `react-codemod`: -- [`replace-reactdom-render`](https://github.com/reactjs/react-codemod?tab=readme-ov-file#replace-reactdom-render) -- [`replace-string-ref`](https://github.com/reactjs/react-codemod?tab=readme-ov-file#replace-string-ref) -- [`replace-act-import`](https://github.com/reactjs/react-codemod?tab=readme-ov-file#replace-act-import) -- [`replace-use-form-state`](https://github.com/reactjs/react-codemod?tab=readme-ov-file#replace-use-form-state) -- [`prop-types-typescript`](TODO) - -This does not include the TypeScript changes. See [TypeScript changes](#typescript-changes) below. - - - -Changes that include a codemod include the command below. - -For a list of all available codemods, see the [`react-codemod` repo](https://github.com/reactjs/react-codemod). - -## Breaking changes {/*breaking-changes*/} - -### Errors in render are not re-thrown {/*errors-in-render-are-not-re-thrown*/} - -In previous versions of React, errors thrown during render were caught and rethrown. In DEV, we would also log to `console.error`, resulting in duplicate error logs. - -In React 19, we've [improved how errors are handled](/blog/2024/04/25/react-19#error-handling) to reduce duplication by not re-throwing: - -- **Uncaught Errors**: Errors that are not caught by an Error Boundary are reported to `window.reportError`. -- **Caught Errors**: Errors that are caught by an Error Boundary are reported to `console.error`. - -This change should not impact most apps, but if your production error reporting relies on errors being re-thrown, you may need to update your error handling. To support this, we've added new methods to `createRoot` and `hydrateRoot` for custom error handling: - -```js [[1, 2, "onUncaughtError"], [2, 5, "onCaughtError"]] -const root = createRoot(container, { - onUncaughtError: (error, errorInfo) => { - // ... log error report - }, - onCaughtError: (error, errorInfo) => { - // ... log error report - } -}); -``` - -For more info, see the docs for [`createRoot`](https://react.dev/reference/react-dom/client/createRoot) and [`hydrateRoot`](https://react.dev/reference/react-dom/client/hydrateRoot). - - -### Removed deprecated React APIs {/*removed-deprecated-react-apis*/} - -#### Removed: `propTypes` and `defaultProps` for functions {/*removed-proptypes-and-defaultprops*/} -`PropTypes` were deprecated in [April 2017 (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` from function components in place of ES6 default parameters. Class components will continue to support `defaultProps` since there is no ES6 alternative. - -```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}

; -} -``` - - - -Codemod `propTypes` to TypeScript with: - -```bash -npx codemod@latest react/prop-types-typescript -``` - - - -#### Removed: Legacy Context using `contextTypes` and `getChildContext` {/*removed-removing-legacy-context*/} - -Legacy Context was deprecated in [October 2018 (v16.6.0)](https://legacy.reactjs.org/blog/2018/10/23/react-v-16-6.html). - -Legacy Context was only available in class components using the APIs `contextTypes` and `getChildContext`, and was replaced with `contextType` 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 {5-11,19-21} -// 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 {2,7,9,15} -// After -const FooContext = React.createContext(); - -class Parent extends React.Component { - render() { - return ( - - - - ); - } -} - -class Child extends React.Component { - static contextType = FooContext; - - render() { - return
{this.context}
; - } -} -``` - -#### Removed: string refs {/*removed-string-refs*/} -String refs were deprecated in [March, 2018 (v16.3.0)](https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html). - -Class components supported string refs before being replaced by ref callbacks due to [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 {4,8} -// Before -class MyComponent extends React.Component { - componentDidMount() { - this.refs.input.focus(); - } - - render() { - return ; - } -} -``` - -```js {4,8} -// After -class MyComponent extends React.Component { - componentDidMount() { - this.input.focus(); - } - - render() { - return this.input = input} />; - } -} -``` - - - -Codemod string refs with `ref` callbacks: - -```bash -npx codemod@latest react/19/replace-string-ref -``` - - - -#### Removed: Module pattern factories {/*removed-module-pattern-factories*/} -Module pattern factories were deprecated in [August 2019 (v16.9.0)](https://legacy.reactjs.org/blog/2019/08/08/react-v16.9.0.html#deprecating-module-pattern-factories). - -This pattern was 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
; -} -``` - -#### Removed: `React.createFactory` {/*removed-createfactory*/} -`createFactory` was deprecated in [February 2020 (v16.13.0)](https://legacy.reactjs.org/blog/2020/02/26/react-v16.13.0.html#deprecating-createfactory). - -Using `createFactory` was common before broad support for JSX, but it's rarely used today and can be replaced with 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 =