Skip to content

Sync with react.dev @ 5138e605 #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion postcss.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ module.exports = {
},
},
},
}
};
6 changes: 4 additions & 2 deletions public/js/jsfiddle-integration-babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(/^\/\/<!\[CDATA\[/, '');
Expand Down
6 changes: 4 additions & 2 deletions public/js/jsfiddle-integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/jsx;harmony=true');
tag.textContent = tag.textContent.replace(/^\/\/<!\[CDATA\[/, '');
Expand Down
4 changes: 2 additions & 2 deletions scripts/headingIDHelpers/walk.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ const fs = require('fs');

module.exports = function walk(dir) {
let results = [];
/**
/**
* If the param is a directory we can return the file
*/
if(dir.includes('md')){
if (dir.includes('md')) {
return [dir];
}
const list = fs.readdirSync(dir);
Expand Down
4 changes: 2 additions & 2 deletions scripts/headingIdLinter.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const validateHeaderIds = require('./headingIDHelpers/validateHeadingIDs');
const generateHeadingIds = require('./headingIDHelpers/generateHeadingIDs');

/**
/**
* yarn lint-heading-ids --> 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')) {
Expand Down
29 changes: 17 additions & 12 deletions src/components/MDX/ErrorDecoder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function parseQueryString(search: string): Array<string | undefined> {
}

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<React.ReactNode | null>(() =>
Expand All @@ -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 (
<code
className={cn(
'block bg-red-100 text-red-600 py-4 px-6 mt-5 rounded-lg',
'whitespace-pre-line block bg-red-100 text-red-600 py-4 px-6 mt-5 rounded-lg',
isReady ? 'opacity-100' : 'opacity-0'
)}>
<b>{message}</b>
Expand Down
4 changes: 2 additions & 2 deletions src/components/MDX/Sandpack/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
},
Expand Down
3 changes: 2 additions & 1 deletion src/content/community/meetups.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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/)
Expand Down
4 changes: 2 additions & 2 deletions src/content/learn/build-a-react-app-from-scratch.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

</Note>

Expand All @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion src/content/learn/reusing-logic-with-custom-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

<Sandpack>

Expand Down
2 changes: 1 addition & 1 deletion src/content/learn/tutorial-tic-tac-toe.md
Original file line number Diff line number Diff line change
Expand Up @@ -2247,7 +2247,7 @@ body {

</Sandpack>

As you iterate through `history` array inside the function you passed to `map`, the `squares` argument goes through each element of `history`, and the `move` argument goes through each array index: `0`, `1`, `2`, …. (In most cases, you'd need the actual array elements, but to render a list of moves you will only need indexes.)
As you iterate through the `history` array inside the function you passed to `map`, the `squares` argument goes through each element of `history`, and the `move` argument goes through each array index: `0`, `1`, `2`, …. (In most cases, you'd need the actual array elements, but to render a list of moves you will only need indexes.)

For each move in the tic-tac-toe game's history, you create a list item `<li>` which contains a button `<button>`. The button has an `onClick` handler which calls a function called `jumpTo` (that you haven't implemented yet).

Expand Down
5 changes: 2 additions & 3 deletions src/content/reference/react/Component.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<CanaryBadge /> 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';
Expand All @@ -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(),
);
}
Expand Down
8 changes: 7 additions & 1 deletion src/content/reference/react/StrictMode.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.**
Expand Down Expand Up @@ -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.

<Note>

When `StrictMode` is enabled for a part of the app, React will only enable behaviors that are possible in production. For example, if `<StrictMode>` 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.

</Note>

---

### Fixing bugs found by double rendering in development {/*fixing-bugs-found-by-double-rendering-in-development*/}
Expand Down
54 changes: 0 additions & 54 deletions src/content/reference/react/captureOwnerStack.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
title: captureOwnerStack
---

<Canary>

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).

</Canary>

<Intro>

`captureOwnerStack` reads the current Owner Stack in development and returns it as a string if available.
Expand Down Expand Up @@ -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
<!DOCTYPE html>
<html lang="en">
Expand Down Expand Up @@ -357,22 +335,6 @@ const container = document.getElementById("root");
createRoot(container).render(<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"
}
}
```

```js src/App.js
function Component() {
return <button onClick={() => console.error('Some console error')}>Trigger console.error()</button>;
Expand Down Expand Up @@ -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"
}
}
```

</Sandpack>

### `captureOwnerStack` is not available {/*captureownerstack-is-not-available*/}
Expand Down
22 changes: 11 additions & 11 deletions src/content/reference/react/useSyncExternalStore.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,43 +405,43 @@ 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);

// ...
}
```

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);

// ...
}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/errors/[errorCode].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function ErrorDecoderPage({
}}
routeTree={sidebarLearn as RouteItem}
section="unknown">
<div className="whitespace-pre-line">{parsedContent}</div>
<div>{parsedContent}</div>
{/* <MaxWidth>
<P>
We highly recommend using the development build locally when debugging
Expand Down
8 changes: 3 additions & 5 deletions src/sidebarReference.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@
{
"title": "cache",
"path": "/reference/react/cache"
}, {
"title": "captureOwnerStack",
"path": "/reference/react/captureOwnerStack"
},
{
"title": "createContext",
Expand Down Expand Up @@ -147,11 +150,6 @@
"title": "experimental_taintUniqueValue",
"path": "/reference/react/experimental_taintUniqueValue",
"version": "canary"
},
{
"title": "captureOwnerStack",
"path": "/reference/react/captureOwnerStack",
"version": "canary"
}
]
},
Expand Down
2 changes: 1 addition & 1 deletion src/siteConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down