Skip to content

Commit 46cd7fc

Browse files
authored
Merge pull request #549 from reactjs/sync-6bfde58c
Sync with react.dev @ 6bfde58
2 parents 192abd3 + dd19001 commit 46cd7fc

26 files changed

+560
-161
lines changed

src/components/DocsFooter.tsx

+9-7
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const DocsPageFooter = memo<DocsPageFooterProps>(
2727
<>
2828
{prevRoute?.path || nextRoute?.path ? (
2929
<>
30-
<div className="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-4 py-4 md:py-12">
30+
<div className="grid grid-cols-1 gap-4 py-4 mx-auto max-w-7xl md:grid-cols-2 md:py-12">
3131
{prevRoute?.path ? (
3232
<FooterLink
3333
type="Previous"
@@ -69,21 +69,23 @@ function FooterLink({
6969
<NextLink
7070
href={href}
7171
className={cn(
72-
'flex gap-x-4 md:gap-x-6 items-center w-full md:w-80 px-4 md:px-5 py-6 border-2 border-transparent text-base leading-base text-link dark:text-link-dark rounded-lg group focus:text-link dark:focus:text-link-dark focus:bg-highlight focus:border-link dark:focus:bg-highlight-dark dark:focus:border-link-dark focus:border-opacity-100 focus:border-2 focus:ring-1 focus:ring-offset-4 focus:ring-blue-40 active:ring-0 active:ring-offset-0 hover:bg-gray-5 dark:hover:bg-gray-80',
72+
'flex gap-x-4 md:gap-x-6 items-center w-full md:min-w-80 md:w-fit md:max-w-md px-4 md:px-5 py-6 border-2 border-transparent text-base leading-base text-link dark:text-link-dark rounded-lg group focus:text-link dark:focus:text-link-dark focus:bg-highlight focus:border-link dark:focus:bg-highlight-dark dark:focus:border-link-dark focus:border-opacity-100 focus:border-2 focus:ring-1 focus:ring-offset-4 focus:ring-blue-40 active:ring-0 active:ring-offset-0 hover:bg-gray-5 dark:hover:bg-gray-80',
7373
{
7474
'flex-row-reverse justify-self-end text-end': type === 'Next',
7575
}
7676
)}>
7777
<IconNavArrow
78-
className="text-tertiary dark:text-tertiary-dark inline group-focus:text-link dark:group-focus:text-link-dark"
78+
className="inline text-tertiary dark:text-tertiary-dark group-focus:text-link dark:group-focus:text-link-dark"
7979
displayDirection={type === 'Previous' ? 'start' : 'end'}
8080
/>
81-
<span>
82-
<span className="block no-underline text-sm tracking-wide text-secondary dark:text-secondary-dark uppercase font-bold group-focus:text-link dark:group-focus:text-link-dark group-focus:text-opacity-100">
81+
<div className="flex flex-col overflow-hidden">
82+
<span className="text-sm font-bold tracking-wide no-underline uppercase text-secondary dark:text-secondary-dark group-focus:text-link dark:group-focus:text-link-dark group-focus:text-opacity-100">
8383
{type}
8484
</span>
85-
<span className="block text-lg group-hover:underline">{title}</span>
86-
</span>
85+
<span className="text-lg break-words group-hover:underline">
86+
{title}
87+
</span>
88+
</div>
8789
</NextLink>
8890
);
8991
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Error Decoder requires reading pregenerated error message from getStaticProps,
2+
// but MDX component doesn't support props. So we use React Context to populate
3+
// the value without prop-drilling.
4+
// TODO: Replace with React.cache + React.use when migrating to Next.js App Router
5+
6+
import {createContext, useContext} from 'react';
7+
8+
const notInErrorDecoderContext = Symbol('not in error decoder context');
9+
10+
export const ErrorDecoderContext = createContext<
11+
| {errorMessage: string | null; errorCode: string | null}
12+
| typeof notInErrorDecoderContext
13+
>(notInErrorDecoderContext);
14+
15+
export const useErrorDecoderParams = () => {
16+
const params = useContext(ErrorDecoderContext);
17+
18+
if (params === notInErrorDecoderContext) {
19+
throw new Error('useErrorDecoder must be used in error decoder pages only');
20+
}
21+
22+
return params;
23+
};

src/components/Layout/Feedback.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import {useState} from 'react';
66
import {useRouter} from 'next/router';
7+
import cn from 'classnames';
78

89
export function Feedback({onSubmit = () => {}}: {onSubmit?: () => void}) {
910
const {asPath} = useRouter();
@@ -60,7 +61,11 @@ function sendGAEvent(isPositive: boolean) {
6061
function SendFeedback({onSubmit}: {onSubmit: () => void}) {
6162
const [isSubmitted, setIsSubmitted] = useState(false);
6263
return (
63-
<div className="max-w-xs w-80 lg:w-auto py-3 shadow-lg rounded-lg m-4 bg-wash dark:bg-gray-95 px-4 flex">
64+
<div
65+
className={cn(
66+
'max-w-xs w-80 lg:w-auto py-3 shadow-lg rounded-lg m-4 bg-wash dark:bg-gray-95 px-4 flex',
67+
{exit: isSubmitted}
68+
)}>
6469
<p className="w-full font-bold text-primary dark:text-primary-dark text-lg me-4">
6570
{isSubmitted ? 'Thank you for your feedback!' : 'Is this page useful?'}
6671
</p>

src/components/MDX/ErrorDecoder.tsx

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import {useEffect, useState} from 'react';
2+
import {useErrorDecoderParams} from '../ErrorDecoderContext';
3+
import cn from 'classnames';
4+
5+
function replaceArgs(
6+
msg: string,
7+
argList: Array<string | undefined>,
8+
replacer = '[missing argument]'
9+
): string {
10+
let argIdx = 0;
11+
return msg.replace(/%s/g, function () {
12+
const arg = argList[argIdx++];
13+
// arg can be an empty string: ?args[0]=&args[1]=count
14+
return arg === undefined || arg === '' ? replacer : arg;
15+
});
16+
}
17+
18+
/**
19+
* Sindre Sorhus <https://sindresorhus.com>
20+
* Released under MIT license
21+
* https://github.com/sindresorhus/linkify-urls/blob/edd75a64a9c36d7025f102f666ddbb6cf0afa7cd/index.js#L4C25-L4C137
22+
*
23+
* The regex is used to extract URL from the string for linkify.
24+
*/
25+
const urlRegex =
26+
/((?<!\+)https?:\/\/(?:www\.)?(?:[-\w.]+?[.@][a-zA-Z\d]{2,}|localhost)(?:[-\w.:%+~#*$!?&/=@]*?(?:,(?!\s))*?)*)/g;
27+
28+
// When the message contains a URL (like https://fb.me/react-refs-must-have-owner),
29+
// make it a clickable link.
30+
function urlify(str: string): React.ReactNode[] {
31+
const segments = str.split(urlRegex);
32+
33+
return segments.map((message, i) => {
34+
if (i % 2 === 1) {
35+
return (
36+
<a
37+
key={i}
38+
target="_blank"
39+
className="underline"
40+
rel="noopener noreferrer"
41+
href={message}>
42+
{message}
43+
</a>
44+
);
45+
}
46+
return message;
47+
});
48+
}
49+
50+
// `?args[]=foo&args[]=bar`
51+
// or `// ?args[0]=foo&args[1]=bar`
52+
function parseQueryString(search: string): Array<string | undefined> {
53+
const rawQueryString = search.substring(1);
54+
if (!rawQueryString) {
55+
return [];
56+
}
57+
58+
const args: Array<string | undefined> = [];
59+
60+
const queries = rawQueryString.split('&');
61+
for (let i = 0; i < queries.length; i++) {
62+
const query = decodeURIComponent(queries[i]);
63+
if (query.startsWith('args[')) {
64+
args.push(query.slice(query.indexOf(']=') + 2));
65+
}
66+
}
67+
68+
return args;
69+
}
70+
71+
export default function ErrorDecoder() {
72+
const {errorMessage} = useErrorDecoderParams();
73+
/** error messages that contain %s require reading location.search */
74+
const hasParams = errorMessage?.includes('%s');
75+
const [message, setMessage] = useState<React.ReactNode | null>(() =>
76+
errorMessage ? urlify(errorMessage) : null
77+
);
78+
79+
const [isReady, setIsReady] = useState(errorMessage == null || !hasParams);
80+
81+
useEffect(() => {
82+
if (errorMessage == null || !hasParams) {
83+
return;
84+
}
85+
86+
setMessage(
87+
urlify(
88+
replaceArgs(
89+
errorMessage,
90+
parseQueryString(window.location.search),
91+
'[missing argument]'
92+
)
93+
)
94+
);
95+
setIsReady(true);
96+
}, [hasParams, errorMessage]);
97+
98+
return (
99+
<code
100+
className={cn(
101+
'block bg-red-100 text-red-600 py-4 px-6 mt-5 rounded-lg',
102+
isReady ? 'opacity-100' : 'opacity-0'
103+
)}>
104+
<b>{message}</b>
105+
</code>
106+
);
107+
}

src/components/MDX/MDXComponents.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import {TocContext} from './TocContext';
3131
import type {Toc, TocItem} from './TocContext';
3232
import {TeamMember} from './TeamMember';
3333

34+
import ErrorDecoder from './ErrorDecoder';
35+
3436
function CodeStep({children, step}: {children: any; step: number}) {
3537
return (
3638
<span
@@ -441,6 +443,7 @@ export const MDXComponents = {
441443
Solution,
442444
CodeStep,
443445
YouTubeIframe,
446+
ErrorDecoder,
444447
};
445448

446449
for (let key in MDXComponents) {

src/content/community/conferences.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Do you know of a local React.js conference? Add it here! (Please keep the list c
1010

1111
## Upcoming Conferences {/*upcoming-conferences*/}
1212

13+
### React Paris 2024 {/*react-paris-2024*/}
14+
March 22, 2024. In-person in Paris, France + Remote (hybrid)
15+
16+
[Website](https://react.paris/) - [Twitter](https://twitter.com/BeJS_) - [LinkedIn](https://www.linkedin.com/events/7150816372074192900/comments/)
17+
1318
### App.js Conf 2024 {/*appjs-conf-2024*/}
1419
May 22 - 24, 2024. In-person in Kraków, Poland + remote
1520

@@ -20,6 +25,11 @@ June 12 - June 14, 2024. Atlanta, GA, USA
2025

2126
[Website](https://renderatl.com) - [Discord](https://www.renderatl.com/discord) - [Twitter](https://twitter.com/renderATL) - [Instagram](https://www.instagram.com/renderatl/) - [Facebook](https://www.facebook.com/renderatl/) - [LinkedIn](https://www.linkedin.com/company/renderatl) - [Podcast](https://www.renderatl.com/culture-and-code#/)
2227

28+
### React Nexus 2024 {/*react-nexus-2024*/}
29+
July 04 & 05, 2024. Bangalore, India (In-person event)
30+
31+
[Website](https://reactnexus.com/) - [Twitter](https://twitter.com/ReactNexus) - [Linkedin](https://www.linkedin.com/company/react-nexus) - [YouTube](https://www.youtube.com/reactify_in)
32+
2333
### React India 2024 {/*react-india-2024*/}
2434
October 17 - 19, 2024. In-person in Goa, India (hybrid event) + Oct 15 2024 - remote day
2535

@@ -50,7 +60,7 @@ October 20 & 23, 2023. In-person in London, UK + remote first interactivity (hyb
5060
### React Brussels 2023 {/*react-brussels-2023*/}
5161
October 13th 2023. In-person in Brussels, Belgium + Remote (hybrid)
5262

53-
[Website](https://www.react.brussels/) - [Twitter](https://twitter.com/BrusselsReact)
63+
[Website](https://www.react.brussels/) - [Twitter](https://twitter.com/BrusselsReact) - [Videos](https://www.youtube.com/playlist?list=PL53Z0yyYnpWh85KeMomUoVz8_brrmh_aC)
5464

5565
### React India 2023 {/*react-india-2023*/}
5666
October 5 - 7, 2023. In-person in Goa, India (hybrid event) + Oct 3 2023 - remote day

src/content/community/meetups.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet
7272
## England (UK) {/*england-uk*/}
7373
* [Manchester](https://www.meetup.com/Manchester-React-User-Group/)
7474
* [React.JS Girls London](https://www.meetup.com/ReactJS-Girls-London/)
75-
* [React London : Bring Your Own Project](https://www.meetup.com/React-London-Bring-Your-Own-Project/)
75+
* [React Advanced London](https://guild.host/react-advanced-london)
76+
* [React Native London](https://guild.host/RNLDN)
7677

7778
## France {/*france*/}
7879
* [Nantes](https://www.meetup.com/React-Nantes/)
@@ -86,7 +87,7 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet
8687
* [Karlsruhe](https://www.meetup.com/react_ka/)
8788
* [Kiel](https://www.meetup.com/Kiel-React-Native-Meetup/)
8889
* [Munich](https://www.meetup.com/ReactJS-Meetup-Munich/)
89-
* [React Berlin](https://www.meetup.com/React-Open-Source/)
90+
* [React Berlin](https://guild.host/react-berlin)
9091

9192
## Greece {/*greece*/}
9293
* [Athens](https://www.meetup.com/React-To-React-Athens-MeetUp/)
@@ -108,7 +109,7 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet
108109
* [Indonesia](https://www.meetup.com/reactindonesia/)
109110

110111
## Ireland {/*ireland*/}
111-
* [Dublin](https://www.meetup.com/ReactJS-Dublin/)
112+
* [Dublin](https://guild.host/reactjs-dublin)
112113

113114
## Israel {/*israel*/}
114115
* [Tel Aviv](https://www.meetup.com/ReactJS-Israel/)
@@ -124,7 +125,7 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet
124125
* [Penang](https://www.facebook.com/groups/reactpenang/)
125126

126127
## Netherlands {/*netherlands*/}
127-
* [Amsterdam](https://www.meetup.com/React-Amsterdam/)
128+
* [Amsterdam](https://guild.host/react-amsterdam)
128129

129130
## New Zealand {/*new-zealand*/}
130131
* [Wellington](https://www.meetup.com/React-Wellington/)
@@ -201,6 +202,7 @@ Do you have a local React.js meetup? Add it here! (Please keep the list alphabet
201202
* [New York, NY - React Ladies](https://www.meetup.com/React-Ladies/)
202203
* [New York, NY - React Native](https://www.meetup.com/React-Native-NYC/)
203204
* [New York, NY - useReactNYC](https://www.meetup.com/useReactNYC/)
205+
* [New York, NY - React.NYC](https://guild.host/react-nyc)
204206
* [Omaha, NE - ReactJS/React Native](https://www.meetup.com/omaha-react-meetup-group/)
205207
* [Palo Alto, CA - React Native](https://www.meetup.com/React-Native-Silicon-Valley/)
206208
* [Philadelphia, PA - ReactJS](https://www.meetup.com/Reactadelphia/)

src/content/community/versioning-policy.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ This section will be most relevant to developers who work on frameworks, librari
8080
Each of React's release channels is designed for a distinct use case:
8181

8282
- [**Latest**](#latest-channel) is for stable, semver React releases. It's what you get when you install React from npm. This is the channel you're already using today. **User-facing applications that consume React directly use this channel.**
83-
- [**Canary**](#canary-channel) tracks the main branch of the React source code repository. Think of these as release candidates for the next semver release. **[Frameworks or other curated setups may choose to use this channel with a pinned version of React.](/blog/2023/05/03/react-canaries) You can also Canaries for integration testing between React and third party projects.**
83+
- [**Canary**](#canary-channel) tracks the main branch of the React source code repository. Think of these as release candidates for the next semver release. **[Frameworks or other curated setups may choose to use this channel with a pinned version of React.](/blog/2023/05/03/react-canaries) You can also use Canaries for integration testing between React and third party projects.**
8484
- [**Experimental**](#experimental-channel) includes experimental APIs and features that aren't available in the stable releases. These also track the main branch, but with additional feature flags turned on. Use this to try out upcoming features before they are released.
8585

8686
All releases are published to npm, but only Latest uses semantic versioning. Prereleases (those in the Canary and Experimental channels) have versions generated from a hash of their contents and the commit date, e.g. `18.3.0-canary-388686f29-20230503` for Canary and `0.0.0-experimental-388686f29-20230503` for Experimental.

src/content/errors/377.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Intro>
2+
3+
In the minified production build of React, we avoid sending down full error messages in order to reduce the number of bytes sent over the wire.
4+
5+
</Intro>
6+
7+
We highly recommend using the development build locally when debugging your app since it tracks additional debug info and provides helpful warnings about potential problems in your apps, but if you encounter an exception while using the production build, this page will reassemble the original error message.
8+
9+
The full text of the error you just encountered is:
10+
11+
<ErrorDecoder />
12+
13+
This error occurs when you pass a BigInt value from a Server Component to a Client Component.

src/content/errors/generic.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Intro>
2+
3+
In the minified production build of React, we avoid sending down full error messages in order to reduce the number of bytes sent over the wire.
4+
5+
</Intro>
6+
7+
We highly recommend using the development build locally when debugging your app since it tracks additional debug info and provides helpful warnings about potential problems in your apps, but if you encounter an exception while using the production build, this page will reassemble the original error message.
8+
9+
The full text of the error you just encountered is:
10+
11+
<ErrorDecoder />

src/content/errors/index.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Intro>
2+
3+
In the minified production build of React, we avoid sending down full error messages in order to reduce the number of bytes sent over the wire.
4+
5+
</Intro>
6+
7+
8+
We highly recommend using the development build locally when debugging your app since it tracks additional debug info and provides helpful warnings about potential problems in your apps, but if you encounter an exception while using the production build, the error message will include just a link to the docs for the error.
9+
10+
For an example, see: [https://ar.react.dev/errors/149](/errors/421).

src/content/learn/updating-arrays-in-state.md

-1
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,6 @@ For example:
409409
```js
410410
import { useState } from 'react';
411411

412-
let nextId = 3;
413412
const initialList = [
414413
{ id: 0, title: 'Big Bellies' },
415414
{ id: 1, title: 'Lunar Landscape' },

src/content/reference/react-dom/components/form.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ canary: true
55

66
<Canary>
77

8-
React's extensions to `<form>` are currently only available in React's canary and experimental channels. In stable releases of React `<form>` works only as a [built-in browser HTML component](https://react.dev/reference/react-dom/components#all-html-components). Learn more about [React's release channels here](/community/versioning-policy#all-release-channels).
8+
React's extensions to `<form>` are currently only available in React's canary and experimental channels. In stable releases of React, `<form>` works only as a [built-in browser HTML component](https://react.dev/reference/react-dom/components#all-html-components). Learn more about [React's release channels here](/community/versioning-policy#all-release-channels).
99

1010
</Canary>
1111

@@ -118,7 +118,7 @@ function AddToCart({productId}) {
118118
}
119119
```
120120

121-
In lieu of using hidden form fields to provide data to the `<form>`'s action, you can call the <CodeStep step={1}>`bind`</CodeStep> method to supply it with extra arguments. This will bind a new argument (<CodeStep step={2}>`productId`</CodeStep>) to the function in addition to the <CodeStep step={3}>`formData`</CodeStep> that is passed as a argument to the function.
121+
In lieu of using hidden form fields to provide data to the `<form>`'s action, you can call the <CodeStep step={1}>`bind`</CodeStep> method to supply it with extra arguments. This will bind a new argument (<CodeStep step={2}>`productId`</CodeStep>) to the function in addition to the <CodeStep step={3}>`formData`</CodeStep> that is passed as an argument to the function.
122122

123123
```jsx [[1, 8, "bind"], [2,8, "productId"], [2,4, "productId"], [3,4, "formData"]]
124124
import { updateCart } from './lib.js';
@@ -278,7 +278,7 @@ export async function deliverMessage(message) {
278278

279279
### Handling form submission errors {/*handling-form-submission-errors*/}
280280

281-
In some cases the function called by a `<form>`'s `action` prop throw an error. You can handle these errors by wrapping `<form>` in an Error Boundary. If the function called by a `<form>`'s `action` prop throws an error, the fallback for the error boundary will be displayed.
281+
In some cases the function called by a `<form>`'s `action` prop throws an error. You can handle these errors by wrapping `<form>` in an Error Boundary. If the function called by a `<form>`'s `action` prop throws an error, the fallback for the error boundary will be displayed.
282282

283283
<Sandpack>
284284

src/content/reference/react-dom/components/input.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ To display an input, render the [built-in browser `<input>`](https://developer.m
3434

3535
<Canary>
3636

37-
React's extensions to the `formAction` prop are currently only available in React's Canary and experimental channels. In stable releases of React `formAction` works only as a [built-in browser HTML component](https://react.dev/reference/react-dom/components#all-html-components). Learn more about [React's release channels here](/community/versioning-policy#all-release-channels).
37+
React's extensions to the `formAction` prop are currently only available in React's Canary and experimental channels. In stable releases of React, `formAction` works only as a [built-in browser HTML component](https://react.dev/reference/react-dom/components#all-html-components). Learn more about [React's release channels here](/community/versioning-policy#all-release-channels).
3838
</Canary>
3939

4040
[`formAction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formaction): A string or function. Overrides the parent `<form action>` for `type="submit"` and `type="image"`. When a URL is passed to `action` the form will behave like a standard HTML form. When a function is passed to `formAction` the function will handle the form submission. See [`<form action>`](/reference/react-dom/components/form#props).

0 commit comments

Comments
 (0)