From 47c818c479de83bb80166965a751cd3782f30a6e Mon Sep 17 00:00:00 2001 From: Delphine Bugner Date: Mon, 5 Feb 2024 19:42:34 +0100 Subject: [PATCH 001/163] feat (conferences) add react connection Paris (#6609) --- src/content/community/conferences.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/content/community/conferences.md b/src/content/community/conferences.md index 0e15359f..ef330187 100644 --- a/src/content/community/conferences.md +++ b/src/content/community/conferences.md @@ -25,6 +25,16 @@ April 19 - 20, 2024. In-person in Miami, FL, USA [Website](https://reactmiami.com/) - [Twitter](https://twitter.com/ReactMiamiConf) +### React Connection 2024 {/*react-connection-2024*/} +April 22, 2024. In-person in Paris, France + +[Website](https://reactconnection.io/) - [Twitter](https://twitter.com/ReactConn) + +### React Native Connection 2024 {/*react-native-connection-2024*/} +April 23, 2024. In-person in Paris, France + +[Website](https://reactnativeconnection.io/) - [Twitter](https://twitter.com/ReactNativeConn) + ### React Conf 2024 {/*react-conf-2024*/} May 15 - 16, 2024. In-person in Henderson, NV, USA + remote From c118938237cc8ef96a8d7680b04f7c8a2a8264fe Mon Sep 17 00:00:00 2001 From: Matt Carroll <7158882+mattcarrollcode@users.noreply.github.com> Date: Tue, 6 Feb 2024 09:36:18 -0800 Subject: [PATCH 002/163] Fix SandpackWithHTMLOutput to use src dir (#6613) --- src/components/MDX/SandpackWithHTMLOutput.tsx | 6 +++--- src/content/reference/react-dom/components/link.md | 10 +++++----- src/content/reference/react-dom/components/meta.md | 2 +- src/content/reference/react-dom/components/script.md | 4 ++-- src/content/reference/react-dom/components/style.md | 2 +- src/content/reference/react-dom/components/title.md | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/MDX/SandpackWithHTMLOutput.tsx b/src/components/MDX/SandpackWithHTMLOutput.tsx index 134da658..51ce28dc 100644 --- a/src/components/MDX/SandpackWithHTMLOutput.tsx +++ b/src/components/MDX/SandpackWithHTMLOutput.tsx @@ -20,7 +20,7 @@ export default function ShowRenderedHTML({children}) { {formatHTML(markup)} - ); + ); }`; const formatHTML = ` @@ -77,8 +77,8 @@ export default memo(function SandpackWithHTMLOutput( ) { const children = [ ...Children.toArray(props.children), - createFile('ShowRenderedHTML.js', ShowRenderedHTML), - createFile('formatHTML.js hidden', formatHTML), + createFile('src/ShowRenderedHTML.js', ShowRenderedHTML), + createFile('src/formatHTML.js hidden', formatHTML), createFile('package.json hidden', packageJSON), ]; return {children}; diff --git a/src/content/reference/react-dom/components/link.md b/src/content/reference/react-dom/components/link.md index 890cf090..fcbb9fab 100644 --- a/src/content/reference/react-dom/components/link.md +++ b/src/content/reference/react-dom/components/link.md @@ -96,7 +96,7 @@ In addition, if the `` is to a stylesheet (namely, it has `rel="stylesheet There are two exception to this special behavior: -* If the link doesn't have a `precedence` prop, there is no special behavior, because the order of stylesheets within the document is significant, so React needs to know how to order this stylesheet relative to others, which you specify using the `precedence` prop. +* If the link doesn't have a `precedence` prop, there is no special behavior, because the order of stylesheets within the document is significant, so React needs to know how to order this stylesheet relative to others, which you specify using the `precedence` prop. * If you supply any of the `onLoad`, `onError`, or `disabled` props, there is no special behavior, because these props indicate that you are managing the loading of the stylesheet manually within your component. This special treatment comes with two caveats: @@ -114,7 +114,7 @@ You can annotate the document with links to related resources such as an icon, c -```js App.js active +```js src/App.js active import ShowRenderedHTML from './ShowRenderedHTML.js'; export default function BlogPage() { @@ -141,7 +141,7 @@ When you want to use a stylesheet, it can be beneficial to call the [preinit](/r -```js App.js active +```js src/App.js active import ShowRenderedHTML from './ShowRenderedHTML.js'; export default function SiteMapPage() { @@ -164,7 +164,7 @@ Stylesheets can conflict with each other, and when they do, the browser goes wit -```js App.js active +```js src/App.js active import ShowRenderedHTML from './ShowRenderedHTML.js'; export default function HomePage() { @@ -195,7 +195,7 @@ If you render the same stylesheet from multiple components, React will place onl -```js App.js active +```js src/App.js active import ShowRenderedHTML from './ShowRenderedHTML.js'; export default function HomePage() { diff --git a/src/content/reference/react-dom/components/meta.md b/src/content/reference/react-dom/components/meta.md index 8489d4a4..801ca2af 100644 --- a/src/content/reference/react-dom/components/meta.md +++ b/src/content/reference/react-dom/components/meta.md @@ -72,7 +72,7 @@ You can render the `` component from any component. React will put a ` -```js App.js active +```js src/App.js active import ShowRenderedHTML from './ShowRenderedHTML.js'; export default function SiteMapPage() { diff --git a/src/content/reference/react-dom/components/script.md b/src/content/reference/react-dom/components/script.md index 50c0af80..a2c4668c 100644 --- a/src/content/reference/react-dom/components/script.md +++ b/src/content/reference/react-dom/components/script.md @@ -91,7 +91,7 @@ If you supply an `src` and `async` prop, your component will suspend while the s -```js App.js active +```js src/App.js active import ShowRenderedHTML from './ShowRenderedHTML.js'; function Map({lat, long}) { @@ -124,7 +124,7 @@ To include an inline script, render the ` +``` + +### Libraries depending on React internals may block upgrades {/*libraries-depending-on-react-internals-may-block-upgrades*/} + +This release includes changes to React internals that may impact libraries that ignore our pleas to not use internals like `SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED`. These changes are necessary to land improvements in React 19, and will not break libraries that follow our guidelines. + +Based on our [Versioning Policy](https://react.dev/community/versioning-policy#what-counts-as-a-breaking-change), these updates are not listed as breaking changes, and we are not including docs for how to upgrade them. The recommendation is to remove any code that depends on internals. + +To reflect the impact of using internals, we have renamed the `SECRET_INTERNALS` suffix to: + +`_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` + +In the future we will more aggressively block accessing internals from React to discourage usage and ensure users are not blocked from upgrading. + +## TypeScript Changes {/*typescript-changes*/} + +### Removed deprecated TypeScript types {/*removed-deprecated-typescript-types*/} + +We've cleaned up the TypeScript types based on the removed APIs in React 19. Some of the removed have types been moved to more relevant packages, and others are no longer needed to describe React's behavior. + + +We've published [`types-react-codemod`](https://github.com/eps1lon/types-react-codemod/) to migrate most type related breaking changes: + +```bash +npx types-react-codemod@latest preset-19 ./path-to-app +``` + +If you have a lot of unsound access to `element.props`, you can run this additional codemod: + +```bash +npx types-react-codemod@latest react-element-default-any-props ./path-to-your-react-ts-files +``` + + + +Check out [`types-react-codemod`](https://github.com/eps1lon/types-react-codemod/) for a list of supported replacements. If you feel a codemod is missing, it can be tracked in the [list of missing React 19 codemods](https://github.com/eps1lon/types-react-codemod/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22React+19%22+label%3Aenhancement). + + +### `ref` cleanups required {/*ref-cleanup-required*/} + +_This change is included in the `react-19` codemod preset as [`no-implicit-ref-callback-return +`](https://github.com/eps1lon/types-react-codemod/#no-implicit-ref-callback-return)._ + +Due to the introduction of ref cleanup functions, returning anything else from a ref callback will now be rejected by TypeScript. The fix is usually to stop using implicit returns: + +```diff [[1, 1, "("], [1, 1, ")"], [2, 2, "{", 15], [2, 2, "}", 1]] +-
(instance = current)} /> ++
{instance = current}} /> +``` + +The original code returned the instance of the `HTMLDivElement` and TypeScript wouldn't know if this was supposed to be a cleanup function or not. + +### `useRef` requires an argument {/*useref-requires-argument*/} + +_This change is included in the `react-19` codemod preset as [`refobject-defaults`](https://github.com/eps1lon/types-react-codemod/#refobject-defaults)._ + +A long-time complaint of how TypeScript and React work has been `useRef`. We've changed the types so that `useRef` now requires an argument. This significantly simplifies its type signature. It'll now behave more like `createContext`. + +```ts +// @ts-expect-error: Expected 1 argument but saw none +useRef(); +// Passes +useRef(undefined); +// @ts-expect-error: Expected 1 argument but saw none +createContext(); +// Passes +createContext(undefined); +``` + +This now also means that all refs are mutable. You'll no longer hit the issue where you can't mutate a ref because you initialised it with `null`: + +```ts +const ref = useRef(null); + +// Cannot assign to 'current' because it is a read-only property +ref.current = 1; +``` + +`MutableRef` is now deprecated in favor of a single `RefObject` type which `useRef` will always return: + +```ts +interface RefObject { + current: T +} + +declare function useRef: RefObject +``` + +`useRef` still has a convenience overload for `useRef(null)` that automatically returns `RefObject`. To ease migration due to the required argument for `useRef`, a convenience overload for `useRef(undefined)` was added that automatically returns `RefObject`. + +Check out [[RFC] Make all refs mutable](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/64772) for prior discussions about this change. + +### Changes to the `ReactElement` TypeScript type {/*changes-to-the-reactelement-typescript-type*/} + +_This change is included in the [`react-element-default-any-props`](https://github.com/eps1lon/types-react-codemod#react-element-default-any-props) codemod._ + +The `props` of React elements now default to `unknown` instead of `any` if the element is typed as `ReactElement`. This does not affect you if you pass a type argument to `ReactElement`: + +```ts +type Example2 = ReactElement<{ id: string }>["props"]; +// ^? { id: string } +``` + +But if you relied on the default, you now have to handle `unknown`: + +```ts +type Example = ReactElement["props"]; +// ^? Before, was 'any', now 'unknown' +``` + +You should only need it if you have a lot of legacy code relying on unsound access of element props. Element introspection only exists as an escape hatch, and you should make it explicit that your props access is unsound via an explicit `any`. + +### The JSX Namespace in TypeScript {/*the-jsx-namespace-in-typescript*/} +This change is included in the `react-19` codemod preset as [`scoped-jsx`](https://github.com/eps1lon/types-react-codemod#scoped-jsx) + +A long-time request is to remove the global `JSX` namespace from our types in favor of `React.JSX`. This helps prevent pollution of global types which prevents conflicts between different UI libraries that leverage JSX. + +You'll now need to wrap module augmentation of the JSX namespace in `declare module "....": + +```diff +// global.d.ts ++ declare module "react" { + namespace JSX { + interface IntrinsicElements { + "my-element": { + myElementProps: string; + }; + } + } ++ } +``` + +The exact module specifier depends on the JSX runtime you specified in the `compilerOptions` of your `tsconfig.json`: + +- For `"jsx": "react-jsx"` it would be `react/jsx-runtime`. +- For `"jsx": "react-jsxdev"` it would be `react/jsx-dev-runtime`. +- For `"jsx": "react"` and `"jsx": "preserve"` it would be `react`. + +### Better `useReducer` typings {/*better-usereducer-typings*/} + +`useReducer` now has improved type inference thanks to [@mfp22](https://github.com/mfp22). + +However, this required a breaking change where `useReducer` doesn't accept the full reducer type as a type parameter but instead either needs none (and rely on contextual typing) or needs both the state and action type. + +The new best practice is _not_ to pass type arguments to `useReducer`. +```diff +- useReducer>(reducer) ++ useReducer(reducer) +``` +This may not work in edge cases where you can explicitly type the state and action, by passing in the `Action` in a tuple: +```diff +- useReducer>(reducer) ++ useReducer(reducer) +``` +If you define the reducer inline, we encourage to annotate the function parameters instead: +```diff +- useReducer>((state, action) => state) ++ useReducer((state: State, action: Action) => state) +``` +This is also what you'd also have to do if you move the reducer outside of the `useReducer` call: + +```ts +const reducer = (state: State, action: Action) => state; +``` + +## Changlog {/*changelog*/} + +### Other Breaking Changes {/*other-breaking-changes*/} + +- **react-dom**: Error for javascript URLs in src/href [#26507](https://github.com/facebook/react/pull/26507) +- **react-dom**: Remove `errorInfo.digest` from `onRecoverableError` [#28222](https://github.com/facebook/react/pull/28222) +- **react-dom**: Remove `unstable_flushControlled` [#26397](https://github.com/facebook/react/pull/26397) +- **react-dom**: Remove `unstable_createEventHandle` [#28271](https://github.com/facebook/react/pull/28271) +- **react-dom**: Remove `unstable_renderSubtreeIntoContainer` [#28271](https://github.com/facebook/react/pull/28271) +- **react-dom**: Remove `unstable_runWithPrioirty` [#28271](https://github.com/facebook/react/pull/28271) +- **react-is**: Remove deprecated methods from `react-is` [28224](https://github.com/facebook/react/pull/28224) + +### Other Notable Changes {/*other-notable-changes*/} + +- **react**: Batch sync, default and continuous lanes [#25700](https://github.com/facebook/react/pull/25700) +- **react**: Don't prerender siblings of suspended component [#26380](https://github.com/facebook/react/pull/26380) +- **react**: Detect infinite update loops caused by render phase updates [#26625](https://github.com/facebook/react/pull/26625) +- **react-dom**: Transitions in popstate are now synchronous [#26025](https://github.com/facebook/react/pull/26025) +- **react-dom**: Remove layout effect warning during SSR [#26395](https://github.com/facebook/react/pull/26395) +- **react-dom**: Warn and don’t set empty string for src/href (except anchor tags) [#28124](https://github.com/facebook/react/pull/28124) + +We'll publish the full changelog with the stable release of React 19. + +--- + +Thanks to [Andrew Clark](https://twitter.com/acdlite), [Eli White](https://twitter.com/Eli_White), [Jack Pope](https://github.com/jackpope), [Jan Kassens](https://github.com/kassens), [Josh Story](https://twitter.com/joshcstory), [Matt Carroll](https://twitter.com/mattcarrollcode), [Noah Lemen](https://twitter.com/noahlemen), [Sophie Alpert](https://twitter.com/sophiebits), and [Sebastian Silbermann](https://twitter.com/sebsilbermann) for reviewing and editing this post. diff --git a/src/content/blog/2024/04/25/react-19.md b/src/content/blog/2024/04/25/react-19.md new file mode 100644 index 00000000..4431b5bf --- /dev/null +++ b/src/content/blog/2024/04/25/react-19.md @@ -0,0 +1,768 @@ +--- +title: "React 19 Beta" +--- + +April 25, 2024 by [The React Team](/community/team) + +--- + + + +This beta release is for libraries to prepare for React 19. App developers should upgrade to 18.3.0 and wait for React 19 stable as we work with libraries and make changes based on feedback. + + + + + +React 19 Beta is now available on npm! + + + +In our [React 19 Beta Upgrade Guide](/blog/2024/04/25/react-19-upgrade-guide), we shared step-by-step instructions for upgrading your app to React 19 Beta. In this post, we'll give an overview of the new features in React 19, and how you can adopt them. + +- [What's new in React 19](#whats-new-in-react-19) +- [Improvements in React 19](#improvements-in-react-19) +- [How to Upgrade](#how-to-upgrade) + +For a list of breaking changes, see the [Upgrade Guide](/blog/2024/04/25/react-19-upgrade-guide). + +--- + +## What's new in React 19 {/*whats-new-in-react-19*/} + +### Actions {/*actions*/} + +A common use case in React apps is to perform a data mutation and then update state in response. For example, when a user submits a form to change their name, you will make an API request, and then handle the response. In the past, you would need to handle pending states, errors, optimistic updates, and sequential requests manually. + +For example, you could handle the pending and error state in `useState`: + +```js +// Before Actions +function UpdateName({}) { + const [name, setName] = useState(""); + const [error, setError] = useState(null); + const [isPending, setIsPending] = useState(false); + + const handleSubmit = async () => { + setIsPending(true); + const error = await updateName(name); + setIsPending(false); + if (error) { + setError(error); + return; + } + redirect("/path"); + }; + + return ( +
+ setName(event.target.value)} /> + + {error &&

{error}

} +
+ ); +} +``` + +In React 19, we're adding support for using async functions in transitions to handle pending states, errors, forms, and optimistic updates automatically. + +For example, you can use `useTransition` to handle the pending state for you: + +```js +// Using pending state from Actions +function UpdateName({}) { + const [name, setName] = useState(""); + const [error, setError] = useState(null); + const [isPending, startTransition] = useTransition(); + + const handleSubmit = async () => { + startTransition(async () => { + const error = await updateName(name); + if (error) { + setError(error); + return; + } + redirect("/path"); + }) + }; + + return ( +
+ setName(event.target.value)} /> + + {error &&

{error}

} +
+ ); +} +``` + +The async transition will immediately set the `isPending` state to true, make the async request(s), and switch `isPending` to false after any transitions. This allows you to keep the current UI responsive and interactive while the data is changing. + + + +#### By convention, functions that use async transitions are called "Actions". {/*by-convention-functions-that-use-async-transitions-are-called-actions*/} + +Actions automatically manage submitting data for you: + +- **Pending state**: Actions provide a pending state that starts at the beginning of a request and automatically resets when the final state update is committed. +- **Optimistic updates**: Actions support the new [`useOptimistic`](#new-feature-optimistic-updates) hook so you can show users instant feedback while the requests are submitting. +- **Error handling**: Actions provide error handling so you can and display Error Boundaries when a request fails, and revert optimistic updates to their original value automatically. +- **Forms**: `
` elements now support passing functions to the `action` and `formAction` props. Passing functions to the `action` props use Actions by default and reset the form automatically after submission. + + + +Building on top of Actions, we're also introducing [`` Actions](#form-actions) to manage forms automatically, [`useOptimistic`](#new-hook-optimistic-updates) to manage optimistic updates, and new hooks [`useActionState`](#new-hook-useactionstate), [`useFormStatus`](#new-hook-useformstatus) hooks to support the common cases for Actions and Forms. + +In React 19, the above example can be simplified to: + +```js +// Using Actions and useActionState +function ChangeName({ name, setName }) { + const [error, submitAction, isPending] = useActionState( + async (previousState, formData) => { + const error = await updateName(formData.get("name")); + if (error) { + return error; + } + redirect("/path"); + } + ); + + return ( + + + + {error &&

{error}

} +
+ ); +} +``` + +In the next section, we'll break down each of the new Action features in React 19. + +### New Hook: `useActionState` {/*new-hook-useactionstate*/} + +To make the common cases easier for Actions, we've added a new hook called `useActionState`: + +```js +const [error, submitAction, isPending] = useActionState(async (previousState, newName) => { + const {error} = await updateName(newName); + if (!error) { + // You can return any result of the action. + // Here, we return only the error. + return error; + } + + // handle success +}); +``` + +`useActionState` accepts a function (the "Action"), and returns a wrapped Action to call. This works because Actions compose. When the wrapped Action is called, `useActionState` will return the last result of the Action as `data`, and the pending state of the Action as `pending`. + + + +`React.useActionState` was previously called `ReactDOM.useFormState` in the Canary releases, but we've renamed it and deprecated `useFormState`. + +See [#28491](https://github.com/facebook/react/pull/28491) for more info. + + + +For more information, see the docs for [`useActionState`](/reference/react/useActionState). + +### `
` Actions {/*form-actions*/} + +Actions are also integrated with React 19's new `` features. We've added support for passing functions as the `action` and `formAction` props of ``, ``, and `
-
-
- - logo by @sawaratsuki1004 - -
-
- - - React - + +
+
+ + logo by @sawaratsuki1004 + +
+
+ + + React + +
-
+