diff --git a/.github/workflows/discord_notify.yml b/.github/workflows/discord_notify.yml index a553b23a0..2f5b2a497 100644 --- a/.github/workflows/discord_notify.yml +++ b/.github/workflows/discord_notify.yml @@ -1,7 +1,7 @@ name: Discord Notify on: - pull_request: + pull_request_target: types: [opened, ready_for_review] permissions: {} @@ -14,7 +14,6 @@ jobs: contents: read with: actor: ${{ github.event.pull_request.user.login }} - is_remote: true notify: if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }} diff --git a/.github/workflows/label_core_team_prs.yml b/.github/workflows/label_core_team_prs.yml index 6099b8fcb..f9b3328ee 100644 --- a/.github/workflows/label_core_team_prs.yml +++ b/.github/workflows/label_core_team_prs.yml @@ -1,7 +1,7 @@ name: Label Core Team PRs on: - pull_request: + pull_request_target: permissions: {} @@ -18,7 +18,6 @@ jobs: contents: read with: actor: ${{ github.event.pull_request.user.login }} - is_remote: true label: if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }} diff --git a/postcss.config.js b/postcss.config.js index 427294522..d55c43c90 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -17,4 +17,4 @@ module.exports = { }, }, }, -} +}; diff --git a/public/js/jsfiddle-integration-babel.js b/public/js/jsfiddle-integration-babel.js index 006c79c8a..56059472f 100644 --- a/public/js/jsfiddle-integration-babel.js +++ b/public/js/jsfiddle-integration-babel.js @@ -4,12 +4,14 @@ // Do not delete or move this file. // Many fiddles reference it so we have to keep it here. -(function() { +(function () { var tag = document.querySelector( 'script[type="application/javascript;version=1.7"]' ); if (!tag || tag.textContent.indexOf('window.onload=function(){') !== -1) { - alert('Bad JSFiddle configuration, please fork the original React JSFiddle'); + alert( + 'Bad JSFiddle configuration, please fork the original React JSFiddle' + ); } tag.setAttribute('type', 'text/babel'); tag.textContent = tag.textContent.replace(/^\/\/ Checks all files and causes an error if heading ID is missing * yarn lint-heading-ids --fix --> Fixes all markdown file's heading IDs * yarn lint-heading-ids path/to/markdown.md --> Checks that particular file for missing heading ID (path can denote a directory or particular file) * yarn lint-heading-ids --fix path/to/markdown.md --> Fixes that particular file's markdown IDs (path can denote a directory or particular file) -*/ + */ const markdownPaths = process.argv.slice(2); if (markdownPaths.includes('--fix')) { diff --git a/src/components/Layout/Page.tsx b/src/components/Layout/Page.tsx index 24d379589..1040e1aa7 100644 --- a/src/components/Layout/Page.tsx +++ b/src/components/Layout/Page.tsx @@ -8,7 +8,7 @@ import {useRouter} from 'next/router'; import {SidebarNav} from './SidebarNav'; import {Footer} from './Footer'; import {Toc} from './Toc'; -// import SocialBanner from '../SocialBanner'; +import SocialBanner from '../SocialBanner'; import {DocsPageFooter} from 'components/DocsFooter'; import {Seo} from 'components/Seo'; import PageHeading from 'components/PageHeading'; @@ -137,7 +137,7 @@ export function Page({ /> )} - {/**/} + { } export default function ErrorDecoder() { - const {errorMessage} = useErrorDecoderParams(); + const {errorMessage, errorCode} = useErrorDecoderParams(); /** error messages that contain %s require reading location.search */ const hasParams = errorMessage?.includes('%s'); const [message, setMessage] = useState(() => @@ -82,23 +82,28 @@ export default function ErrorDecoder() { if (errorMessage == null || !hasParams) { return; } + const args = parseQueryString(window.location.search); + let message = errorMessage; + if (errorCode === '418') { + // Hydration errors have a %s for the diff, but we don't add that to the args for security reasons. + message = message.replace(/%s$/, ''); - setMessage( - urlify( - replaceArgs( - errorMessage, - parseQueryString(window.location.search), - '[missing argument]' - ) - ) - ); + // Before React 19.1, the error message didn't have an arg, and was always HTML. + if (args.length === 0) { + args.push('HTML'); + } else if (args.length === 1 && args[0] === '') { + args[0] = 'HTML'; + } + } + + setMessage(urlify(replaceArgs(message, args, '[missing argument]'))); setIsReady(true); - }, [hasParams, errorMessage]); + }, [errorCode, hasParams, errorMessage]); return ( {message} diff --git a/src/components/MDX/Sandpack/template.ts b/src/components/MDX/Sandpack/template.ts index 42f02f6a6..7fbd537e7 100644 --- a/src/components/MDX/Sandpack/template.ts +++ b/src/components/MDX/Sandpack/template.ts @@ -28,8 +28,8 @@ root.render( eject: 'react-scripts eject', }, dependencies: { - react: '19.0.0-rc-3edc000d-20240926', - 'react-dom': '19.0.0-rc-3edc000d-20240926', + react: '^19.1.0', + 'react-dom': '^19.1.0', 'react-scripts': '^5.0.0', }, }, diff --git a/src/components/SocialBanner.tsx b/src/components/SocialBanner.tsx index 79724109e..6995eee5f 100644 --- a/src/components/SocialBanner.tsx +++ b/src/components/SocialBanner.tsx @@ -7,7 +7,7 @@ import {useRef, useEffect} from 'react'; import cn from 'classnames'; import {ExternalLink} from './ExternalLink'; -const bannerText = 'Guarda lo Stream di React Conf il 15-16 Maggio.'; +const bannerText = 'Unisciti a noi per React Conf il 7-8 ottobre.'; const bannerLink = 'https://conf.react.dev/'; const bannerLinkText = 'Maggiori informazioni.'; diff --git a/src/content/community/conferences.md b/src/content/community/conferences.md index 46636d4c9..17dd96159 100644 --- a/src/content/community/conferences.md +++ b/src/content/community/conferences.md @@ -10,16 +10,6 @@ Do you know of a local React.js conference? Add it here! (Please keep the list c ## Upcoming Conferences {/*upcoming-conferences*/} -### React Paris 2025 {/*react-paris-2025*/} -March 20 - 21, 2025. In-person in Paris, France (hybrid event) - -[Website](https://react.paris/) - [Twitter](https://x.com/BeJS_) - -### React Native Connection 2025 {/*react-native-connection-2025*/} -April 3 (Reanimated Training) + April 4 (Conference), 2025. Paris, France. - -[Website](https://reactnativeconnection.io/) - [X](https://x.com/reactnativeconn) - [Bluesky](https://bsky.app/profile/reactnativeconnect.bsky.social) - ### CityJS London 2025 {/*cityjs-london*/} April 23 - 25, 2025. In-person in London, UK @@ -50,6 +40,11 @@ September 2-4, 2025. Wrocław, Poland. [Website](https://www.reactuniverseconf.com/) - [Twitter](https://twitter.com/react_native_eu) - [LinkedIn](https://www.linkedin.com/events/reactuniverseconf7163919537074118657/) +### React Conf 2025 {/*react-conf-2025*/} +October 7-8, 2025. Henderson, Nevada, USA and free livestream + +[Website](https://conf.react.dev/) - [Twitter](https://x.com/reactjs) - [Bluesky](https://bsky.app/profile/react.dev) + ### React India 2025 {/*react-india-2025*/} October 31 - November 01, 2025. In-person in Goa, India (hybrid event) + Oct 15 2025 - remote day @@ -58,6 +53,16 @@ October 31 - November 01, 2025. In-person in Goa, India (hybrid event) + Oct 15 ## Past Conferences {/*past-conferences*/} +### React Paris 2025 {/*react-paris-2025*/} +March 20 - 21, 2025. In-person in Paris, France (hybrid event) + +[Website](https://react.paris/) - [Twitter](https://x.com/BeJS_) + +### React Native Connection 2025 {/*react-native-connection-2025*/} +April 3 (Reanimated Training) + April 4 (Conference), 2025. Paris, France. + +[Website](https://reactnativeconnection.io/) - [X](https://x.com/reactnativeconn) - [Bluesky](https://bsky.app/profile/reactnativeconnect.bsky.social) + ### React Day Berlin 2024 {/*react-day-berlin-2024*/} December 13 & 16, 2024. In-person in Berlin, Germany + remote (hybrid event) diff --git a/src/content/community/meetups.md b/src/content/community/meetups.md index 906c170de..186740341 100644 --- a/src/content/community/meetups.md +++ b/src/content/community/meetups.md @@ -47,6 +47,9 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet ## Colombia {/*colombia*/} * [Medellin](https://www.meetup.com/React-Medellin/) +## Czechia {/*czechia*/} +* [Prague](https://guild.host/react-prague/) + ## Denmark {/*denmark*/} * [Aalborg](https://www.meetup.com/Aalborg-React-React-Native-Meetup/) * [Aarhus](https://www.meetup.com/Aarhus-ReactJS-Meetup/) @@ -78,7 +81,7 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet * [Thessaloniki](https://www.meetup.com/Thessaloniki-ReactJS-Meetup/) ## India {/*india*/} -* [Ahmedabad](https://www.meetup.com/react-ahmedabad/) +* [Ahmedabad](https://reactahmedabad.dev/) * [Bangalore (React)](https://www.meetup.com/ReactJS-Bangalore/) * [Bangalore (React Native)](https://www.meetup.com/React-Native-Bangalore-Meetup) * [Chennai](https://www.linkedin.com/company/chennaireact) @@ -166,6 +169,7 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet * [Cleveland, OH - ReactJS](https://www.meetup.com/Cleveland-React/) * [Columbus, OH - ReactJS](https://www.meetup.com/ReactJS-Columbus-meetup/) * [Dallas, TX - ReactJS](https://www.meetup.com/ReactDallas/) +* [Denver, CO - React Denver](https://reactdenver.com/) * [Detroit, MI - Detroit React User Group](https://www.meetup.com/Detroit-React-User-Group/) * [Indianapolis, IN - React.Indy](https://www.meetup.com/React-Indy) * [Irvine, CA - ReactJS](https://www.meetup.com/ReactJS-OC/) diff --git a/src/content/learn/build-a-react-app-from-scratch.md b/src/content/learn/build-a-react-app-from-scratch.md index e5b396c7e..721f670dd 100644 --- a/src/content/learn/build-a-react-app-from-scratch.md +++ b/src/content/learn/build-a-react-app-from-scratch.md @@ -65,7 +65,7 @@ Rsbuild includes built-in support for React features like fast refresh, JSX, Typ #### Metro for React Native {/*react-native*/} -If you'd you're starting from scratch with React Native you'll need to use [Metro](https://metrobundler.dev/), the JavaScript bundler for React Native. Metro supports bundling for platforms like iOS and Android, but lacks many features when compared to the tools here. We recommend starting with Vite, Parcel, or Rsbuild unless your project requires React Native support. +If you're starting from scratch with React Native you'll need to use [Metro](https://metrobundler.dev/), the JavaScript bundler for React Native. Metro supports bundling for platforms like iOS and Android, but lacks many features when compared to the tools here. We recommend starting with Vite, Parcel, or Rsbuild unless your project requires React Native support. @@ -83,7 +83,7 @@ Routers are a core part of modern applications, and are usually integrated with We suggest using: -- [React Router](https://reactrouter.com/start/framework/custom) +- [React Router](https://reactrouter.com/start/data/custom) - [Tanstack Router](https://tanstack.com/router/latest) diff --git a/src/content/learn/reusing-logic-with-custom-hooks.md b/src/content/learn/reusing-logic-with-custom-hooks.md index 67de5e97f..ea8d0a313 100644 --- a/src/content/learn/reusing-logic-with-custom-hooks.md +++ b/src/content/learn/reusing-logic-with-custom-hooks.md @@ -1333,7 +1333,7 @@ export function useOnlineStatus() { In the above example, `useOnlineStatus` is implemented with a pair of [`useState`](/reference/react/useState) and [`useEffect`.](/reference/react/useEffect) However, this isn't the best possible solution. There is a number of edge cases it doesn't consider. For example, it assumes that when the component mounts, `isOnline` is already `true`, but this may be wrong if the network already went offline. You can use the browser [`navigator.onLine`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine) API to check for that, but using it directly would not work on the server for generating the initial HTML. In short, this code could be improved. -Luckily, React 18 includes a dedicated API called [`useSyncExternalStore`](/reference/react/useSyncExternalStore) which takes care of all of these problems for you. Here is how your `useOnlineStatus` Hook, rewritten to take advantage of this new API: +React includes a dedicated API called [`useSyncExternalStore`](/reference/react/useSyncExternalStore) which takes care of all of these problems for you. Here is your `useOnlineStatus` Hook, rewritten to take advantage of this new API: diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index 0a3933949..adc6a8d37 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -90,6 +90,15 @@ React will display `` in the `root`, and take over managing the DOM insid * If you call `render` on the same root more than once, React will update the DOM as necessary to reflect the latest JSX you passed. React will decide which parts of the DOM can be reused and which need to be recreated by ["matching it up"](/learn/preserving-and-resetting-state) with the previously rendered tree. Calling `render` on the same root again is similar to calling the [`set` function](/reference/react/useState#setstate) on the root component: React avoids unnecessary DOM updates. +* Although rendering is synchronous once it starts, `root.render(...)` is not. This means code after `root.render()` may run before any effects (`useLayoutEffect`, `useEffect`) of that specific render are fired. This is usually fine and rarely needs adjustment. In rare cases where effect timing matters, you can wrap `root.render(...)` in [`flushSync`](https://react.dev/reference/react-dom/client/flushSync) to ensure the initial render runs fully synchronously. + + ```js + const root = createRoot(document.getElementById('root')); + root.render(); + // 🚩 The HTML will not include the rendered yet: + console.log(document.body.innerHTML); + ``` + --- ### `root.unmount()` {/*root-unmount*/} diff --git a/src/content/reference/react-dom/hooks/index.md b/src/content/reference/react-dom/hooks/index.md index 73eefae75..5dfb07d82 100644 --- a/src/content/reference/react-dom/hooks/index.md +++ b/src/content/reference/react-dom/hooks/index.md @@ -14,7 +14,7 @@ The `react-dom` package contains Hooks that are only supported for web applicati *Forms* let you create interactive controls for submitting information. To manage forms in your components, use one of these Hooks: -* [`useFormStatus`](/reference/react-dom/hooks/useFormStatus) allows you to make updates to the UI based on the status of the a form. +* [`useFormStatus`](/reference/react-dom/hooks/useFormStatus) allows you to make updates to the UI based on the status of a form. ```js function Form({ action }) { diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 0821d1593..8e58af8ff 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -1273,7 +1273,7 @@ By default, if your application throws an error during rendering, React will rem To implement an error boundary component, you need to provide [`static getDerivedStateFromError`](#static-getderivedstatefromerror) which lets you update state in response to an error and display an error message to the user. You can also optionally implement [`componentDidCatch`](#componentdidcatch) to add some extra logic, for example, to log the error to an analytics service. - With [`captureOwnerStack`](/reference/react/captureOwnerStack) you can include the Owner Stack during development. +With [`captureOwnerStack`](/reference/react/captureOwnerStack) you can include the Owner Stack during development. ```js {9-12,14-27} import * as React from 'react'; @@ -1298,8 +1298,7 @@ class ErrorBoundary extends React.Component { // in div (created by App) // in App info.componentStack, - // Only available in react@canary. - // Warning: Owner Stack is not available in production. + // Warning: `captureOwnerStack` is not available in production. React.captureOwnerStack(), ); } diff --git a/src/content/reference/react/StrictMode.md b/src/content/reference/react/StrictMode.md index 5b62794bc..1af02ccd1 100644 --- a/src/content/reference/react/StrictMode.md +++ b/src/content/reference/react/StrictMode.md @@ -88,7 +88,7 @@ Strict Mode enables the following checks in development: - Your components will [re-render an extra time](#fixing-bugs-found-by-double-rendering-in-development) to find bugs caused by impure rendering. - Your components will [re-run Effects an extra time](#fixing-bugs-found-by-re-running-effects-in-development) to find bugs caused by missing Effect cleanup. -- Your components will [re-run ref callbacks an extra time](#fixing-bugs-found-by-cleaning-up-and-re-attaching-dom-refs-in-development) to find bugs caused by missing ref cleanup. +- Your components will [re-run ref callbacks an extra time](#fixing-bugs-found-by-re-running-ref-callbacks-in-development) to find bugs caused by missing ref cleanup. - Your components will [be checked for usage of deprecated APIs.](#fixing-deprecation-warnings-enabled-by-strict-mode) **All of these checks are development-only and do not impact the production build.** @@ -122,6 +122,12 @@ function App() { In this example, Strict Mode checks will not run against the `Header` and `Footer` components. However, they will run on `Sidebar` and `Content`, as well as all of the components inside them, no matter how deep. + + +When `StrictMode` is enabled for a part of the app, React will only enable behaviors that are possible in production. For example, if `` is not enabled at the root of the app, it will not [re-run Effects an extra time](#fixing-bugs-found-by-re-running-effects-in-development) on initial mount, since this would cause child effects to double fire without the parent effects, which cannot happen in production. + + + --- ### Fixing bugs found by double rendering in development {/*fixing-bugs-found-by-double-rendering-in-development*/} diff --git a/src/content/reference/react/captureOwnerStack.md b/src/content/reference/react/captureOwnerStack.md index f8ed21a8c..6d8cc502d 100644 --- a/src/content/reference/react/captureOwnerStack.md +++ b/src/content/reference/react/captureOwnerStack.md @@ -2,12 +2,6 @@ title: captureOwnerStack --- - - -The `captureOwnerStack` API is currently only available in React's Canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). - - - `captureOwnerStack` reads the current Owner Stack in development and returns it as a string if available. @@ -126,22 +120,6 @@ createRoot(document.createElement('div'), { ); ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "latest" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test --env=jsdom", - "eject": "react-scripts eject" - } -} -``` - ```html public/index.html hidden @@ -357,22 +335,6 @@ const container = document.getElementById("root"); createRoot(container).render(); ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "latest" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test --env=jsdom", - "eject": "react-scripts eject" - } -} -``` - ```js src/App.js function Component() { return ; @@ -417,22 +379,6 @@ export default function App() { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "latest" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test --env=jsdom", - "eject": "react-scripts eject" - } -} -``` - ### `captureOwnerStack` is not available {/*captureownerstack-is-not-available*/} diff --git a/src/content/reference/react/useId.md b/src/content/reference/react/useId.md index c6be96fde..a77cf7a72 100644 --- a/src/content/reference/react/useId.md +++ b/src/content/reference/react/useId.md @@ -46,6 +46,8 @@ function PasswordField() { * `useId` **should not be used to generate keys** in a list. [Keys should be generated from your data.](/learn/rendering-lists#where-to-get-your-key) +* `useId` currently cannot be used in [async Server Components](/reference/rsc/server-components#async-components-with-server-components). + --- ## Usage {/*usage*/} diff --git a/src/content/reference/react/useSyncExternalStore.md b/src/content/reference/react/useSyncExternalStore.md index 05e0c0831..ce989a2a4 100644 --- a/src/content/reference/react/useSyncExternalStore.md +++ b/src/content/reference/react/useSyncExternalStore.md @@ -405,14 +405,14 @@ If your store data is mutable, your `getSnapshot` function should return an immu This `subscribe` function is defined *inside* a component so it is different on every re-render: -```js {4-7} +```js {2-5} function ChatIndicator() { - const isOnline = useSyncExternalStore(subscribe, getSnapshot); - // 🚩 Always a different function, so React will resubscribe on every re-render function subscribe() { // ... } + + const isOnline = useSyncExternalStore(subscribe, getSnapshot); // ... } @@ -420,28 +420,28 @@ function ChatIndicator() { React will resubscribe to your store if you pass a different `subscribe` function between re-renders. If this causes performance issues and you'd like to avoid resubscribing, move the `subscribe` function outside: -```js {6-9} -function ChatIndicator() { - const isOnline = useSyncExternalStore(subscribe, getSnapshot); +```js {1-4} +// ✅ Always the same function, so React won't need to resubscribe +function subscribe() { // ... } -// ✅ Always the same function, so React won't need to resubscribe -function subscribe() { +function ChatIndicator() { + const isOnline = useSyncExternalStore(subscribe, getSnapshot); // ... } ``` Alternatively, wrap `subscribe` into [`useCallback`](/reference/react/useCallback) to only resubscribe when some argument changes: -```js {4-8} +```js {2-5} function ChatIndicator({ userId }) { - const isOnline = useSyncExternalStore(subscribe, getSnapshot); - // ✅ Same function as long as userId doesn't change const subscribe = useCallback(() => { // ... }, [userId]); + + const isOnline = useSyncExternalStore(subscribe, getSnapshot); // ... } diff --git a/src/pages/errors/[errorCode].tsx b/src/pages/errors/[errorCode].tsx index de9eab5bb..a67c5742d 100644 --- a/src/pages/errors/[errorCode].tsx +++ b/src/pages/errors/[errorCode].tsx @@ -36,7 +36,7 @@ export default function ErrorDecoderPage({ }} routeTree={sidebarLearn as RouteItem} section="unknown"> -
{parsedContent}
+
{parsedContent}
{/*

We highly recommend using the development build locally when debugging diff --git a/src/sidebarReference.json b/src/sidebarReference.json index a044c9f5b..851b544d0 100644 --- a/src/sidebarReference.json +++ b/src/sidebarReference.json @@ -117,6 +117,9 @@ { "title": "cache", "path": "/reference/react/cache" + }, { + "title": "captureOwnerStack", + "path": "/reference/react/captureOwnerStack" }, { "title": "createContext", @@ -147,11 +150,6 @@ "title": "experimental_taintUniqueValue", "path": "/reference/react/experimental_taintUniqueValue", "version": "canary" - }, - { - "title": "captureOwnerStack", - "path": "/reference/react/captureOwnerStack", - "version": "canary" } ] }, diff --git a/src/siteConfig.js b/src/siteConfig.js index cef6a5623..6a2d3237a 100644 --- a/src/siteConfig.js +++ b/src/siteConfig.js @@ -2,7 +2,7 @@ * Copyright (c) Facebook, Inc. and its affiliates. */ exports.siteConfig = { - version: '19', + version: '19.1', // -------------------------------------- // Translations should replace these lines: languageCode: 'it',