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/MDX/ErrorDecoder.tsx b/src/components/MDX/ErrorDecoder.tsx index b04fa9f79..a9b7455df 100644 --- a/src/components/MDX/ErrorDecoder.tsx +++ b/src/components/MDX/ErrorDecoder.tsx @@ -69,7 +69,7 @@ function parseQueryString(search: string): Array { } 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/content/community/meetups.md b/src/content/community/meetups.md index b3290a004..186740341 100644 --- a/src/content/community/meetups.md +++ b/src/content/community/meetups.md @@ -81,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) @@ -169,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/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/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 3a8748fa6..e731dcec4 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: 'en',