diff --git a/next-env.d.ts b/next-env.d.ts index 52e831b43..3cd7048ed 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,5 +1,6 @@ /// /// +/// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/public/images/tutorial/react-starter-code-codesandbox.png b/public/images/tutorial/react-starter-code-codesandbox.png old mode 100644 new mode 100755 index d65f161bc..b01e18297 Binary files a/public/images/tutorial/react-starter-code-codesandbox.png and b/public/images/tutorial/react-starter-code-codesandbox.png differ diff --git a/src/components/DocsFooter.tsx b/src/components/DocsFooter.tsx index 5f2330e7e..93c2ca125 100644 --- a/src/components/DocsFooter.tsx +++ b/src/components/DocsFooter.tsx @@ -80,7 +80,7 @@ function FooterLink({ />
- {type} + {type === 'Previous' ? 'Previous' : 'Next'} {title} diff --git a/src/components/Icon/IconArrowSmall.tsx b/src/components/Icon/IconArrowSmall.tsx index 4a3d3ad02..a70717c9d 100644 --- a/src/components/Icon/IconArrowSmall.tsx +++ b/src/components/Icon/IconArrowSmall.tsx @@ -19,6 +19,7 @@ export const IconArrowSmall = memo< const classes = cn(className, { 'rotate-180': displayDirection === 'left', 'rotate-180 rtl:rotate-0': displayDirection === 'start', + 'rtl:rotate-180': displayDirection === 'end', 'rotate-90': displayDirection === 'down', }); return ( diff --git a/src/components/MDX/Challenges/Navigation.tsx b/src/components/MDX/Challenges/Navigation.tsx index 736db093c..b4d8c0924 100644 --- a/src/components/MDX/Challenges/Navigation.tsx +++ b/src/components/MDX/Challenges/Navigation.tsx @@ -108,7 +108,7 @@ export function Navigation({ onClick={handleScrollLeft} aria-label="Scroll left" className={cn( - 'bg-secondary-button dark:bg-secondary-button-dark h-8 px-2 rounded-l border-gray-20 border-r rtl:rotate-180', + 'bg-secondary-button dark:bg-secondary-button-dark h-8 px-2 rounded-l rtl:rounded-r rtl:rounded-l-none border-gray-20 border-r rtl:border-l rtl:border-r-0', { 'text-primary dark:text-primary-dark': canScrollLeft, 'text-gray-30': !canScrollLeft, @@ -120,7 +120,7 @@ export function Navigation({ onClick={handleScrollRight} aria-label="Scroll right" className={cn( - 'bg-secondary-button dark:bg-secondary-button-dark h-8 px-2 rounded-e rtl:rotate-180', + 'bg-secondary-button dark:bg-secondary-button-dark h-8 px-2 rounded-e', { 'text-primary dark:text-primary-dark': canScrollRight, 'text-gray-30': !canScrollRight, diff --git a/src/components/MDX/Sandpack/ClearButton.tsx b/src/components/MDX/Sandpack/ClearButton.tsx new file mode 100644 index 000000000..868f9fb66 --- /dev/null +++ b/src/components/MDX/Sandpack/ClearButton.tsx @@ -0,0 +1,22 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + */ + +import * as React from 'react'; +import {IconClose} from '../../Icon/IconClose'; +export interface ClearButtonProps { + onClear: () => void; +} + +export function ClearButton({onClear}: ClearButtonProps) { + return ( + + ); +} diff --git a/src/components/MDX/Sandpack/NavigationBar.tsx b/src/components/MDX/Sandpack/NavigationBar.tsx index bf2c3186c..d115868dd 100644 --- a/src/components/MDX/Sandpack/NavigationBar.tsx +++ b/src/components/MDX/Sandpack/NavigationBar.tsx @@ -17,7 +17,8 @@ import { useSandpackNavigation, } from '@codesandbox/sandpack-react/unstyled'; import {OpenInCodeSandboxButton} from './OpenInCodeSandboxButton'; -import {ResetButton} from './ResetButton'; +import {ReloadButton} from './ReloadButton'; +import {ClearButton} from './ClearButton'; import {DownloadButton} from './DownloadButton'; import {IconChevron} from '../../Icon/IconChevron'; import {Listbox} from '@headlessui/react'; @@ -95,7 +96,7 @@ export function NavigationBar({providedFiles}: {providedFiles: Array}) { // Note: in a real useEvent, onContainerResize would be omitted. }, [isMultiFile, onContainerResize]); - const handleReset = () => { + const handleClear = () => { /** * resetAllFiles must come first, otherwise * the previous content will appear for a second @@ -103,13 +104,13 @@ export function NavigationBar({providedFiles}: {providedFiles: Array}) { * * Plus, it should only prompt if there's any file changes */ - if ( - sandpack.editorState === 'dirty' && - confirm('Reset all your edits too?') - ) { + if (sandpack.editorState === 'dirty' && confirm('Clear all your edits?')) { sandpack.resetAllFiles(); } + refresh(); + }; + const handleReload = () => { refresh(); }; @@ -188,7 +189,8 @@ export function NavigationBar({providedFiles}: {providedFiles: Array}) { className="px-3 flex items-center justify-end text-start" translate="yes"> - + + {activeFile.endsWith('.tsx') && ( void; +export interface ReloadButtonProps { + onReload: () => void; } -export function ResetButton({onReset}: ResetButtonProps) { +export function ReloadButton({onReload}: ReloadButtonProps) { return ( ); } diff --git a/src/content/blog/2025/04/21/react-compiler-rc.md b/src/content/blog/2025/04/21/react-compiler-rc.md index ecbbb8747..2ebbf3bae 100644 --- a/src/content/blog/2025/04/21/react-compiler-rc.md +++ b/src/content/blog/2025/04/21/react-compiler-rc.md @@ -57,23 +57,23 @@ During the RC period, we encourage all React users to try the compiler and provi As noted in the Beta announcement, React Compiler is compatible with React 17 and up. If you are not yet on React 19, you can use React Compiler by specifying a minimum target in your compiler config, and adding `react-compiler-runtime` as a dependency. You can find docs on this [here](https://react.dev/learn/react-compiler#using-react-compiler-with-react-17-or-18). ## Migrating from eslint-plugin-react-compiler to eslint-plugin-react-hooks {/*migrating-from-eslint-plugin-react-compiler-to-eslint-plugin-react-hooks*/} -If you have already installed eslint-plugin-react-compiler, you can now remove it and use `eslint-plugin-react-hooks@6.0.0-rc.1`. Many thanks to [@michaelfaith](https://bsky.app/profile/michael.faith) for contributing to this improvement! +If you have already installed eslint-plugin-react-compiler, you can now remove it and use `eslint-plugin-react-hooks@rc`. Many thanks to [@michaelfaith](https://bsky.app/profile/michael.faith) for contributing to this improvement! To install: npm -{`npm install --save-dev eslint-plugin-react-hooks@6.0.0-rc.1`} +{`npm install --save-dev eslint-plugin-react-hooks@rc`} pnpm -{`pnpm add --save-dev eslint-plugin-react-hooks@6.0.0-rc.1`} +{`pnpm add --save-dev eslint-plugin-react-hooks@rc`} yarn -{`yarn add --dev eslint-plugin-react-hooks@6.0.0-rc.1`} +{`yarn add --dev eslint-plugin-react-hooks@rc`} ```js diff --git a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md index 0f54d02b4..333334073 100644 --- a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md +++ b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md @@ -2521,7 +2521,7 @@ export default function App() { const { url } = useRouter(); // Define a default animation of .slow-fade. - // See animations.css for the animation definiton. + // See animations.css for the animation definition. return ( {url === '/' ? :
} diff --git a/src/content/community/conferences.md b/src/content/community/conferences.md index 5efaf19ba..c9d08be69 100644 --- a/src/content/community/conferences.md +++ b/src/content/community/conferences.md @@ -10,36 +10,6 @@ Bạn có biết về hội nghị React.js ở địa phương hay khu vực c ## Upcoming Conferences {/*upcoming-conferences*/} -### CityJS London 2025 {/*cityjs-london*/} -April 23 - 25, 2025. In-person in London, UK - -[Website](https://london.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) - -### App.js Conf 2025 {/*appjs-conf-2025*/} -May 28 - 30, 2025. In-person in Kraków, Poland + remote - -[Website](https://appjs.co) - [Twitter](https://twitter.com/appjsconf) - -### CityJS Athens 2025 {/*cityjs-athens*/} -May 27 - 31, 2025. In-person in Athens, Greece - -[Website](https://athens.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) - -### React Norway 2025 {/*react-norway-2025*/} -June 13, 2025. In-person in Oslo, Norway + remote (virtual event) - -[Website](https://reactnorway.com/) - [Twitter](https://x.com/ReactNorway) - -### React Summit 2025 {/*react-summit-2025*/} -June 13 - 17, 2025. In-person in Amsterdam, Netherlands + remote (hybrid event) - -[Website](https://reactsummit.com/) - [Twitter](https://x.com/reactsummit) - -### React Nexus 2025 {/*react-nexus-2025*/} -July 03 - 05, 2025. In-person in Bangalore, India - -[Website](https://reactnexus.com/) - [Twitter](https://x.com/ReactNexus) - [Bluesky](https://bsky.app/profile/reactnexus.com) - [Linkedin](https://www.linkedin.com/company/react-nexus) - [YouTube](https://www.youtube.com/reactify_in) - ### React Universe Conf 2025 {/*react-universe-conf-2025*/} September 2-4, 2025. Wrocław, Poland. @@ -50,6 +20,11 @@ October 2-4, 2025. Alicante, Spain. [Website](https://reactalicante.es/) - [Twitter](https://x.com/ReactAlicante) - [Bluesky](https://bsky.app/profile/reactalicante.es) - [YouTube](https://www.youtube.com/channel/UCaSdUaITU1Cz6PvC97A7e0w) +### RenderCon Kenya 2025 {/*rendercon-kenya-2025*/} +October 04, 2025. Nairobi, Kenya + +[Website](https://rendercon.org/) - [Twitter](https://twitter.com/renderconke) - [LinkedIn](https://www.linkedin.com/company/renderconke/) - [YouTube](https://www.youtube.com/channel/UC0bCcG8gHUL4njDOpQGcMIA) + ### React Conf 2025 {/*react-conf-2025*/} October 7-8, 2025. Henderson, Nevada, USA and free livestream @@ -60,6 +35,12 @@ October 31 - November 01, 2025. In-person in Goa, India (hybrid event) + Oct 15 [Website](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) + +### CityJS New Delhi 2025 {/*cityjs-newdelhi*/} +November 6-7, 2025. In-person in New Delhi, India + +[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) + ### React Summit US 2025 {/*react-summit-us-2025*/} November 18 - 21, 2025. In-person in New York, USA + remote (hybrid event) @@ -70,13 +51,49 @@ November 28 & December 1, 2025. In-person in London, UK + online (hybrid event) [Website](https://reactadvanced.com/) - [Twitter](https://x.com/reactadvanced) +### React Paris 2026 {/*react-paris-2026*/} +March 26 - 27, 2026. In-person in Paris, France (hybrid event) + +[Website](https://react.paris/) - [Twitter](https://x.com/BeJS_) + ## Past Conferences {/*past-conferences*/} + +### React Nexus 2025 {/*react-nexus-2025*/} +July 03 - 05, 2025. In-person in Bangalore, India + +[Website](https://reactnexus.com/) - [Twitter](https://x.com/ReactNexus) - [Bluesky](https://bsky.app/profile/reactnexus.com) - [Linkedin](https://www.linkedin.com/company/react-nexus) - [YouTube](https://www.youtube.com/reactify_in) + +### React Summit 2025 {/*react-summit-2025*/} +June 13 - 17, 2025. In-person in Amsterdam, Netherlands + remote (hybrid event) + +[Website](https://reactsummit.com/) - [Twitter](https://x.com/reactsummit) + +### React Norway 2025 {/*react-norway-2025*/} +June 13, 2025. In-person in Oslo, Norway + remote (virtual event) + +[Website](https://reactnorway.com/) - [Twitter](https://x.com/ReactNorway) + +### CityJS Athens 2025 {/*cityjs-athens*/} +May 27 - 31, 2025. In-person in Athens, Greece + +[Website](https://athens.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) + +### App.js Conf 2025 {/*appjs-conf-2025*/} +May 28 - 30, 2025. In-person in Kraków, Poland + remote + +[Website](https://appjs.co) - [Twitter](https://twitter.com/appjsconf) + +### CityJS London 2025 {/*cityjs-london*/} +April 23 - 25, 2025. In-person in London, UK + +[Website](https://london.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) + ### 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_) +[Website](https://react.paris/) - [Twitter](https://x.com/BeJS_) - [YouTube](https://www.youtube.com/playlist?list=PL53Z0yyYnpWitP8Zv01TSEQmKLvuRh_Dj) ### React Native Connection 2025 {/*react-native-connection-2025*/} April 3 (Reanimated Training) + April 4 (Conference), 2025. Paris, France. diff --git a/src/content/community/meetups.md b/src/content/community/meetups.md index 1145b74ea..63c695fed 100644 --- a/src/content/community/meetups.md +++ b/src/content/community/meetups.md @@ -58,6 +58,7 @@ Bạn đã có React.js meetup tại quốc gia của bạn chưa? Thêm nó và * [Manchester](https://www.meetup.com/Manchester-React-User-Group/) * [React.JS Girls London](https://www.meetup.com/ReactJS-Girls-London/) * [React Advanced London](https://guild.host/react-advanced-london) +* [React Native Liverpool](https://www.meetup.com/react-native-liverpool/) * [React Native London](https://guild.host/RNLDN) ## Phần Lan {/*finland*/} @@ -137,7 +138,14 @@ Bạn đã có React.js meetup tại quốc gia của bạn chưa? Thêm nó và ## Bồ Đào Nha {/*portugal*/} * [Lisbon](https://www.meetup.com/JavaScript-Lisbon/) +<<<<<<< HEAD ## Tây Ban Nha {/*spain*/} +======= +## Scotland (UK) {/*scotland-uk*/} +* [Edinburgh](https://www.meetup.com/react-edinburgh/) + +## Spain {/*spain*/} +>>>>>>> d34c6a2c6fa49fc6f64b07aa4fa979d86d41c4e8 * [Barcelona](https://www.meetup.com/ReactJS-Barcelona/) ## Sri Lanka {/*sri-lanka*/} 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 b5f29e9af..185b693b1 100644 --- a/src/content/learn/build-a-react-app-from-scratch.md +++ b/src/content/learn/build-a-react-app-from-scratch.md @@ -122,7 +122,7 @@ For code-splitting instructions, see your build tool docs: ### Improving Application Performance {/*improving-application-performance*/} -Since the build tool you select only support single page apps (SPAs) you'll need to implement other [rendering patterns](https://www.patterns.dev/vanilla/rendering-patterns) like server-side rendering (SSR), static site generation (SSG), and/or React Server Components (RSC). Even if you don't need these features at first, in the future there may be some routes that would benefit SSR, SSG or RSC. +Since the build tool you select only supports single page apps (SPAs), you'll need to implement other [rendering patterns](https://www.patterns.dev/vanilla/rendering-patterns) like server-side rendering (SSR), static site generation (SSG), and/or React Server Components (RSC). Even if you don't need these features at first, in the future there may be some routes that would benefit SSR, SSG or RSC. * **Single-page apps (SPA)** load a single HTML page and dynamically updates the page as the user interacts with the app. SPAs are easier to get started with, but they can have slower initial load times. SPAs are the default architecture for most build tools. diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index 2053f936b..2d1ee8685 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -211,7 +211,7 @@ This is because **Hooks must only be called at the top-level of your component.* One possible way around this is to get a single ref to their parent element, and then use DOM manipulation methods like [`querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) to "find" the individual child nodes from it. However, this is brittle and can break if your DOM structure changes. -Another solution is to **pass a function to the `ref` attribute.** This is called a [`ref` callback.](/reference/react-dom/components/common#ref-callback) React will call your ref callback with the DOM node when it's time to set the ref, and with `null` when it's time to clear it. This lets you maintain your own array or a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), and access any ref by its index or some kind of ID. +Another solution is to **pass a function to the `ref` attribute.** This is called a [`ref` callback.](/reference/react-dom/components/common#ref-callback) React will call your ref callback with the DOM node when it's time to set the ref, and call the cleanup function returned from the callback when it's time to clear it. This lets you maintain your own array or a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), and access any ref by its index or some kind of ID. This example shows how you can use this approach to scroll to an arbitrary node in a long list: @@ -247,13 +247,13 @@ export default function CatFriends() {
    {catList.map((cat) => (
  • { const map = getMap(); map.set(cat, node); @@ -263,7 +263,7 @@ export default function CatFriends() { }; }} > - +
  • ))}
@@ -273,11 +273,22 @@ export default function CatFriends() { } function setupCatList() { - const catList = []; - for (let i = 0; i < 10; i++) { - catList.push("https://loremflickr.com/320/240/cat?lock=" + i); + const catCount = 10; + const catList = new Array(catCount) + for (let i = 0; i < catCount; i++) { + let imageUrl = ''; + if (i < 5) { + imageUrl = "https://placecats.com/neo/320/240"; + } else if (i < 8) { + imageUrl = "https://placecats.com/millie/320/240"; + } else { + imageUrl = "https://placecats.com/bella/320/240"; + } + catList[i] = { + id: i, + imageUrl, + }; } - return catList; } @@ -876,12 +887,30 @@ export default function CatFriends() { ); } -const catList = []; -for (let i = 0; i < 10; i++) { - catList.push({ +const catCount = 10; +const catList = new Array(catCount); +for (let i = 0; i < catCount; i++) { + const bucket = Math.floor(Math.random() * catCount) % 2; + let imageUrl = ''; + switch (bucket) { + case 0: { + imageUrl = "https://placecats.com/neo/250/200"; + break; + } + case 1: { + imageUrl = "https://placecats.com/millie/250/200"; + break; + } + case 2: + default: { + imageUrl = "https://placecats.com/bella/250/200"; + break; + } + } + catList[i] = { id: i, - imageUrl: 'https://loremflickr.com/250/200/cat?lock=' + i - }); + imageUrl, + }; } ``` @@ -961,7 +990,7 @@ export default function CatFriends() { behavior: 'smooth', block: 'nearest', inline: 'center' - }); + }); }}> Next @@ -993,12 +1022,30 @@ export default function CatFriends() { ); } -const catList = []; -for (let i = 0; i < 10; i++) { - catList.push({ +const catCount = 10; +const catList = new Array(catCount); +for (let i = 0; i < catCount; i++) { + const bucket = Math.floor(Math.random() * catCount) % 2; + let imageUrl = ''; + switch (bucket) { + case 0: { + imageUrl = "https://placecats.com/neo/250/200"; + break; + } + case 1: { + imageUrl = "https://placecats.com/millie/250/200"; + break; + } + case 2: + default: { + imageUrl = "https://placecats.com/bella/250/200"; + break; + } + } + catList[i] = { id: i, - imageUrl: 'https://loremflickr.com/250/200/cat?lock=' + i - }); + imageUrl, + }; } ``` diff --git a/src/content/learn/react-compiler/installation.md b/src/content/learn/react-compiler/installation.md index 3606c9c6d..a40b1f5af 100644 --- a/src/content/learn/react-compiler/installation.md +++ b/src/content/learn/react-compiler/installation.md @@ -176,16 +176,7 @@ Install the ESLint plugin: npm install -D eslint-plugin-react-hooks@rc -Then enable the compiler rule in your ESLint configuration: - -```js {3} -// .eslintrc.js -module.exports = { - rules: { - 'react-hooks/react-compiler': 'error', - }, -}; -``` +If you haven't already configured eslint-plugin-react-hooks, follow the [installation instructions in the readme](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/README.md#installation). The compiler rule is enabled by default in the latest RC, so no additional configuration is needed. The ESLint rule will: - Identify violations of the [Rules of React](/reference/rules) diff --git a/src/content/learn/react-compiler/introduction.md b/src/content/learn/react-compiler/introduction.md index 440c66ab6..9957b8227 100644 --- a/src/content/learn/react-compiler/introduction.md +++ b/src/content/learn/react-compiler/introduction.md @@ -50,6 +50,21 @@ const ExpensiveComponent = memo(function ExpensiveComponent({ data, onClick }) { }); ``` + + + +This manual memoization has a subtle bug that breaks memoization: + +```js [[2, 1, "() => handleClick(item)"]] + handleClick(item)} /> +``` + +Even though `handleClick` is wrapped in `useCallback`, the arrow function `() => handleClick(item)` creates a new function every time the component renders. This means that `Item` will always receive a new `onClick` prop, breaking memoization. + +React Compiler is able to optimize this correctly with or without the arrow function, ensuring that `Item` only re-renders when `props.onClick` changes. + + + ### After React Compiler {/*after-react-compiler*/} With React Compiler, you write the same code without manual memoization: @@ -74,7 +89,7 @@ function ExpensiveComponent({ data, onClick }) { _[See this example in the React Compiler Playground](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAogB4AOCmYeAbggMIQC2Fh1OAFMEQCYBDHAIA0RQowA2eOAGsiAXwCURYAB1iROITA4iFGBERgwCPgBEhAogF4iCStVoMACoeO1MAcy6DhSgG4NDSItHT0ACwFMPkkmaTlbIi48HAQWFRsAPlUQ0PFMKRlZFLSWADo8PkC8hSDMPJgEHFhiLjzQgB4+eiyO-OADIwQTM0thcpYBClL02xz2zXz8zoBJMqJZBABPG2BU9Mq+BQKiuT2uTJyomLizkoOMk4B6PqX8pSUFfs7nnro3qEapgFCAFEA)_ -React Compiler automatically applies the equivalent optimizations, ensuring your app only re-renders when necessary. +React Compiler automatically applies the optimal memoization, ensuring your app only re-renders when necessary. #### What kind of memoization does React Compiler add? {/*what-kind-of-memoization-does-react-compiler-add*/} @@ -154,7 +169,7 @@ Next.js users can enable the swc-invoked React Compiler by using [v15.3.1](https ## What should I do about useMemo, useCallback, and React.memo? {/*what-should-i-do-about-usememo-usecallback-and-reactmemo*/} -If you are using React Compiler, [`useMemo`](/reference/react/useMemo), [`useCallback`](/reference/react/useCallback), and [`React.memo`](/reference/react/memo) can be removed. React Compiler adds automatic memoization more precisely and granularly than is possible with these hooks. If you choose to keep manual memoization, React Compiler will analyze them and determine if your manual memoization matches its automatically inferred memoization. If there isn't a match, the compiler will choose to bail out of optimizing that component. +React Compiler adds automatic memoization more precisely and granularly than is possible with [`useMemo`](/reference/react/useMemo), [`useCallback`](/reference/react/useCallback), and [`React.memo`](/reference/react/memo). If you choose to keep manual memoization, React Compiler will analyze them and determine if your manual memoization matches its automatically inferred memoization. If there isn't a match, the compiler will choose to bail out of optimizing that component. This is done out of caution as a common anti-pattern with manual memoization is using it for correctness. This means your app depends on specific values being memoized to work properly. For example, in order to prevent an infinite loop, you may have memoized some values to stop a `useEffect` call from firing. This breaks the Rules of React, but since it can potentially be dangerous for the compiler to automatically remove manual memoization, the compiler will just bail out instead. You should manually remove your handwritten memoization and verify that your app still works as expected. diff --git a/src/content/learn/reusing-logic-with-custom-hooks.md b/src/content/learn/reusing-logic-with-custom-hooks.md index b6562e2df..de68dd190 100644 --- a/src/content/learn/reusing-logic-with-custom-hooks.md +++ b/src/content/learn/reusing-logic-with-custom-hooks.md @@ -1419,10 +1419,29 @@ Similar to a [design system,](https://uxdesign.cc/everything-you-need-to-know-ab #### Will React provide any built-in solution for data fetching? {/*will-react-provide-any-built-in-solution-for-data-fetching*/} +Today, with the [`use`](/reference/react/use#streaming-data-from-server-to-client) API, data can be read in render by passing a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to `use`: + +```js {1,4,11} +import { use, Suspense } from "react"; + +function Message({ messagePromise }) { + const messageContent = use(messagePromise); + return

Here is the message: {messageContent}

; +} + +export function MessageContainer({ messagePromise }) { + return ( + ⌛Downloading message...

}> + +
+ ); +} +``` + We're still working out the details, but we expect that in the future, you'll write data fetching like this: ```js {1,4,6} -import { use } from 'react'; // Not available yet! +import { use } from 'react'; function ShippingForm({ country }) { const cities = use(fetch(`/api/cities?country=${country}`)); diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md index c80c7f5fe..115c2a9a5 100644 --- a/src/content/learn/tutorial-tic-tac-toe.md +++ b/src/content/learn/tutorial-tic-tac-toe.md @@ -283,7 +283,7 @@ In CodeSandbox you'll see three main sections: ![CodeSandbox with starter code](../images/tutorial/react-starter-code-codesandbox.png) -1. The _Files_ section with a list of files like `App.js`, `index.js`, `styles.css` and a folder called `public` +1. The _Files_ section with a list of files like `App.js`, `index.js`, `styles.css` in `src` folder and a folder called `public` 1. The _code editor_ where you'll see the source code of your selected file 1. The _browser_ section where you'll see how the code you've written will be displayed diff --git a/src/content/learn/typescript.md b/src/content/learn/typescript.md index c348e6496..5ed72a1f5 100644 --- a/src/content/learn/typescript.md +++ b/src/content/learn/typescript.md @@ -32,13 +32,13 @@ All [production-grade React frameworks](/learn/start-a-new-react-project#full-st To install the latest version of React's type definitions: -npm install @types/react @types/react-dom +npm install --save-dev @types/react @types/react-dom The following compiler options need to be set in your `tsconfig.json`: 1. `dom` must be included in [`lib`](https://www.typescriptlang.org/tsconfig/#lib) (Note: If no `lib` option is specified, `dom` is included by default). -1. [`jsx`](https://www.typescriptlang.org/tsconfig/#jsx) must be set to one of the valid options. `preserve` should suffice for most applications. +2. [`jsx`](https://www.typescriptlang.org/tsconfig/#jsx) must be set to one of the valid options. `preserve` should suffice for most applications. If you're publishing a library, consult the [`jsx` documentation](https://www.typescriptlang.org/tsconfig/#jsx) on what value to choose. ## TypeScript with React Components {/*typescript-with-react-components*/} diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 356637bcd..b17b1a40b 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -38,7 +38,7 @@ To create interactive controls for submitting information, render the [built-in `
` supports all [common element props.](/reference/react-dom/components/common#common-props) -[`action`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action): a URL or function. When a URL is passed to `action` the form will behave like the HTML form component. When a function is passed to `action` the function will handle the form submission. The function passed to `action` may be async and will be called with a single argument containing the [form data](https://developer.mozilla.org/en-US/docs/Web/API/FormData) of the submitted form. The `action` prop can be overridden by a `formAction` attribute on a `