diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 8330e30d2..d963758b1 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -11,18 +11,26 @@ jobs: analyze: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20.x' + cache: yarn + cache-dependency-path: yarn.lock - - name: Install dependencies - uses: bahmutov/npm-install@v1.7.10 + - name: Restore cached node_modules + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + + - name: Install deps + run: yarn install --frozen-lockfile - name: Restore next build - uses: actions/cache@v3 + uses: actions/cache@v4 id: restore-build-cache env: cache-name: cache-next-build diff --git a/.github/workflows/site_lint.yml b/.github/workflows/site_lint.yml index 34ca6d7b8..36f7642c9 100644 --- a/.github/workflows/site_lint.yml +++ b/.github/workflows/site_lint.yml @@ -14,14 +14,22 @@ jobs: name: Lint on node 20.x and ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Use Node.js 20.x - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20.x + cache: yarn + cache-dependency-path: yarn.lock - - name: Install deps and build (with cache) - uses: bahmutov/npm-install@v1.8.32 + - name: Restore cached node_modules + uses: actions/cache@v4 + with: + path: "**/node_modules" + key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + + - name: Install deps + run: yarn install --frozen-lockfile - name: Lint codebase run: yarn ci-check diff --git a/public/.well-known/atproto-did b/public/.well-known/atproto-did new file mode 100644 index 000000000..ad8b0a36b --- /dev/null +++ b/public/.well-known/atproto-did @@ -0,0 +1 @@ +did:plc:uorpbnp2q32vuvyeruwauyhe \ No newline at end of file diff --git a/public/images/docs/diagrams/prerender.dark.png b/public/images/docs/diagrams/prerender.dark.png new file mode 100644 index 000000000..1e7d67e13 Binary files /dev/null and b/public/images/docs/diagrams/prerender.dark.png differ diff --git a/public/images/docs/diagrams/prerender.png b/public/images/docs/diagrams/prerender.png new file mode 100644 index 000000000..ababa5493 Binary files /dev/null and b/public/images/docs/diagrams/prerender.png differ diff --git a/public/images/docs/diagrams/prewarm.dark.png b/public/images/docs/diagrams/prewarm.dark.png new file mode 100644 index 000000000..461406039 Binary files /dev/null and b/public/images/docs/diagrams/prewarm.dark.png differ diff --git a/public/images/docs/diagrams/prewarm.png b/public/images/docs/diagrams/prewarm.png new file mode 100644 index 000000000..f6ec1c49d Binary files /dev/null and b/public/images/docs/diagrams/prewarm.png differ diff --git a/src/components/Icon/IconBsky.tsx b/src/components/Icon/IconBsky.tsx new file mode 100644 index 000000000..6645152dd --- /dev/null +++ b/src/components/Icon/IconBsky.tsx @@ -0,0 +1,24 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + */ + +import {memo} from 'react'; + +export const IconBsky = memo(function IconBsky( + props +) { + return ( + + + + ); +}); diff --git a/src/components/Icon/IconRocket.tsx b/src/components/Icon/IconRocket.tsx new file mode 100644 index 000000000..457736c7c --- /dev/null +++ b/src/components/Icon/IconRocket.tsx @@ -0,0 +1,32 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + */ + +import {memo} from 'react'; + +export const IconRocket = memo< + JSX.IntrinsicElements['svg'] & {title?: string; size?: 's' | 'md'} +>(function IconRocket({className, size = 'md'}) { + return ( + + ); +}); diff --git a/src/components/Layout/Footer.tsx b/src/components/Layout/Footer.tsx index 0bb562754..f912ba2ae 100644 --- a/src/components/Layout/Footer.tsx +++ b/src/components/Layout/Footer.tsx @@ -8,6 +8,7 @@ import cn from 'classnames'; import {ExternalLink} from 'components/ExternalLink'; import {IconFacebookCircle} from 'components/Icon/IconFacebookCircle'; import {IconTwitter} from 'components/Icon/IconTwitter'; +import {IconBsky} from 'components/Icon/IconBsky'; import {IconGitHub} from 'components/Icon/IconGitHub'; export function Footer() { @@ -366,6 +367,12 @@ export function Footer() { className={socialLinkClasses}> + + + {title}{' '} - {canary && ( + {version === 'major' && ( + + React 19 + + )} + {version === 'canary' && ( )} diff --git a/src/components/Layout/Sidebar/SidebarRouteTree.tsx b/src/components/Layout/Sidebar/SidebarRouteTree.tsx index 3f058073c..54f02b925 100644 --- a/src/components/Layout/Sidebar/SidebarRouteTree.tsx +++ b/src/components/Layout/Sidebar/SidebarRouteTree.tsx @@ -87,7 +87,7 @@ export function SidebarRouteTree({ path, title, routes, - canary, + version, heading, hasSectionHeader, sectionHeader, @@ -121,7 +121,7 @@ export function SidebarRouteTree({ selected={selected} level={level} title={title} - canary={canary} + version={version} isExpanded={isExpanded} hideArrow={isForceExpanded} /> @@ -145,7 +145,7 @@ export function SidebarRouteTree({ selected={selected} level={level} title={title} - canary={canary} + version={version} /> ); diff --git a/src/components/Layout/getRouteMeta.tsx b/src/components/Layout/getRouteMeta.tsx index 3564dd738..b3d14725d 100644 --- a/src/components/Layout/getRouteMeta.tsx +++ b/src/components/Layout/getRouteMeta.tsx @@ -19,8 +19,8 @@ export type RouteTag = export interface RouteItem { /** Page title (for the sidebar) */ title: string; - /** Optional canary flag for heading */ - canary?: boolean; + /** Optional version flag for heading */ + version?: 'canary' | 'major'; /** Optional page description for heading */ description?: string; /* Additional meta info for page tagging */ diff --git a/src/components/MDX/Diagram.tsx b/src/components/MDX/Diagram.tsx index 7920661da..649f48dff 100644 --- a/src/components/MDX/Diagram.tsx +++ b/src/components/MDX/Diagram.tsx @@ -15,8 +15,8 @@ interface DiagramProps { function Caption({text}: {text: string}) { return ( -
-
+
+
{text}
diff --git a/src/components/MDX/ExpandableCallout.tsx b/src/components/MDX/ExpandableCallout.tsx index d1916da8a..b4239fbb5 100644 --- a/src/components/MDX/ExpandableCallout.tsx +++ b/src/components/MDX/ExpandableCallout.tsx @@ -8,8 +8,16 @@ import {IconNote} from '../Icon/IconNote'; import {IconWarning} from '../Icon/IconWarning'; import {IconPitfall} from '../Icon/IconPitfall'; import {IconCanary} from '../Icon/IconCanary'; +import {IconRocket} from '../Icon/IconRocket'; -type CalloutVariants = 'deprecated' | 'pitfall' | 'note' | 'wip' | 'canary'; +type CalloutVariants = + | 'deprecated' + | 'pitfall' + | 'note' + | 'wip' + | 'canary' + | 'major' + | 'rsc'; interface ExpandableCalloutProps { children: React.ReactNode; @@ -59,6 +67,22 @@ const variantMap = { overlayGradient: 'linear-gradient(rgba(249, 247, 243, 0), rgba(249, 247, 243, 1)', }, + major: { + title: 'React 19', + Icon: IconRocket, + containerClasses: 'bg-blue-10 dark:bg-blue-60 dark:bg-opacity-20', + textColor: 'text-blue-50 dark:text-blue-40', + overlayGradient: + 'linear-gradient(rgba(249, 247, 243, 0), rgba(249, 247, 243, 1)', + }, + rsc: { + title: 'React Server Components', + Icon: null, + containerClasses: 'bg-blue-10 dark:bg-blue-60 dark:bg-opacity-20', + textColor: 'text-blue-50 dark:text-blue-40', + overlayGradient: + 'linear-gradient(rgba(249, 247, 243, 0), rgba(249, 247, 243, 1)', + }, }; function ExpandableCallout({children, type = 'note'}: ExpandableCalloutProps) { @@ -72,9 +96,11 @@ function ExpandableCallout({children, type = 'note'}: ExpandableCalloutProps) { variant.containerClasses )}>

- + {variant.Icon && ( + + )} {variant.title}

diff --git a/src/components/MDX/MDXComponents.tsx b/src/components/MDX/MDXComponents.tsx index 29c96a0c7..10fb5ba82 100644 --- a/src/components/MDX/MDXComponents.tsx +++ b/src/components/MDX/MDXComponents.tsx @@ -97,6 +97,14 @@ const Canary = ({children}: {children: React.ReactNode}) => ( {children} ); +const NextMajor = ({children}: {children: React.ReactNode}) => ( + {children} +); + +const RSC = ({children}: {children: React.ReactNode}) => ( + {children} +); + const CanaryBadge = ({title}: {title: string}) => ( ( ); +const NextMajorBadge = ({title}: {title: string}) => ( + + React 19 + +); + +const RSCBadge = ({title}: {title: string}) => ( + + RSC + +); + const Blockquote = ({ children, ...props @@ -483,6 +511,10 @@ export const MDXComponents = { Note, Canary, CanaryBadge, + NextMajor, + NextMajorBadge, + RSC, + RSCBadge, PackageImport, ReadBlogPost, Recap, diff --git a/src/components/MDX/Sandpack/template.ts b/src/components/MDX/Sandpack/template.ts index 9ead18a14..42f02f6a6 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: '^18.0.0', - 'react-dom': '^18.0.0', + react: '19.0.0-rc-3edc000d-20240926', + 'react-dom': '19.0.0-rc-3edc000d-20240926', 'react-scripts': '^5.0.0', }, }, diff --git a/src/components/MDX/TeamMember.tsx b/src/components/MDX/TeamMember.tsx index eaf74187e..e1b9198d8 100644 --- a/src/components/MDX/TeamMember.tsx +++ b/src/components/MDX/TeamMember.tsx @@ -6,6 +6,7 @@ import * as React from 'react'; import Image from 'next/image'; import {IconTwitter} from '../Icon/IconTwitter'; import {IconThreads} from '../Icon/IconThreads'; +import {IconBsky} from '../Icon/IconBsky'; import {IconGitHub} from '../Icon/IconGitHub'; import {ExternalLink} from '../ExternalLink'; import {H3} from './Heading'; @@ -19,6 +20,7 @@ interface TeamMemberProps { photo: string; twitter?: string; threads?: string; + bsky?: string; github?: string; personal?: string; } @@ -33,6 +35,7 @@ export function TeamMember({ github, twitter, threads, + bsky, personal, }: TeamMemberProps) { if (name == null || title == null || permalink == null || children == null) { @@ -62,11 +65,11 @@ export function TeamMember({ {title &&
{title}
} {children} -
+
{twitter && (
@@ -77,7 +80,7 @@ export function TeamMember({ {threads && (
@@ -85,6 +88,17 @@ export function TeamMember({
)} + {bsky && ( +
+ + + {bsky} + +
+ )} {github && (
-The improvements added to React 19 RC require some breaking changes, but we've worked to make the upgrade as smooth as possible, and we don't expect the changes to impact most apps. +The improvements added to React 19 require some breaking changes, but we've worked to make the upgrade as smooth as possible, and we don't expect the changes to impact most apps. @@ -38,7 +38,7 @@ In this post, we will guide you through the steps for upgrading to React 19: - [TypeScript changes](#typescript-changes) - [Changelog](#changelog) -If you'd like to help us test React 19, follow the steps in this upgrade guide and [report any issues](https://github.com/facebook/react/issues/new?assignees=&labels=React+19&projects=&template=19.md&title=%5BReact+19%5D) you encounter. For a list of new features added to React 19, see the [React 19 release post](/blog/2024/04/25/react-19). +If you'd like to help us test React 19, follow the steps in this upgrade guide and [report any issues](https://github.com/facebook/react/issues/new?assignees=&labels=React+19&projects=&template=19.md&title=%5BReact+19%5D) you encounter. For a list of new features added to React 19, see the [React 19 release post](/blog/2024/12/05/react-19). --- ## Installing {/*installing*/} @@ -70,28 +70,23 @@ We expect most apps will not be affected since the transform is enabled in most To install the latest version of React and React DOM: ```bash -npm install --save-exact react@rc react-dom@rc +npm install --save-exact react@^19.0.0 react-dom@^19.0.0 ``` Or, if you're using Yarn: ```bash -yarn add --exact react@rc react-dom@rc +yarn add --exact react@^19.0.0 react-dom@^19.0.0 ``` -If you're using TypeScript, you also need to update the types. Once React 19 is released as stable, you can install the types as usual from `@types/react` and `@types/react-dom`. Until the stable release, the types are available in different packages which need to be enforced in your `package.json`: +If you're using TypeScript, you also need to update the types. +```bash +npm install --save-exact @types/react@^19.0.0 @types/react-dom@^19.0.0 +``` -```json -{ - "dependencies": { - "@types/react": "npm:types-react@rc", - "@types/react-dom": "npm:types-react-dom@rc" - }, - "overrides": { - "@types/react": "npm:types-react@rc", - "@types/react-dom": "npm:types-react-dom@rc" - } -} +Or, if you're using Yarn: +```bash +yarn add --exact @types/react@^19.0.0 @types/react-dom@^19.0.0 ``` We're also including a codemod for the most common replacements. See [TypeScript changes](#typescript-changes) below. @@ -536,6 +531,24 @@ When double rendering in Strict Mode in development, `useMemo` and `useCallback` As with all Strict Mode behaviors, these features are designed to proactively surface bugs in your components during development so you can fix them before they are shipped to production. For example, during development, Strict Mode will double-invoke ref callback functions on initial mount, to simulate what happens when a mounted component is replaced by a Suspense fallback. +### Improvements to Suspense {/*improvements-to-suspense*/} + +In React 19, when a component suspends, React will immediately commit the fallback of the nearest Suspense boundary without waiting for the entire sibling tree to render. After the fallback commits, React schedules another render for the suspended siblings to "pre-warm" lazy requests in the rest of the tree: + + + +Previously, when a component suspended, the suspended siblings were rendered and then the fallback was committed. + + + + + +In React 19, when a component suspends, the fallback is committed and then the suspended siblings are rendered. + + + +This change means Suspense fallbacks display faster, while still warming lazy requests in the suspended tree. + ### UMD builds removed {/*umd-builds-removed*/} UMD was widely used in the past as a convenient way to load React without a build step. Now, there are modern alternatives for loading modules as scripts in HTML documents. Starting with React 19, React will no longer produce UMD builds to reduce the complexity of its testing and release process. @@ -717,12 +730,12 @@ const reducer = (state: State, action: Action) => state; ### Other breaking changes {/*other-breaking-changes*/} -- **react-dom**: Error for javascript URLs in src/href [#26507](https://github.com/facebook/react/pull/26507) +- **react-dom**: Error for javascript URLs in `src` and `href` [#26507](https://github.com/facebook/react/pull/26507) - **react-dom**: Remove `errorInfo.digest` from `onRecoverableError` [#28222](https://github.com/facebook/react/pull/28222) - **react-dom**: Remove `unstable_flushControlled` [#26397](https://github.com/facebook/react/pull/26397) - **react-dom**: Remove `unstable_createEventHandle` [#28271](https://github.com/facebook/react/pull/28271) - **react-dom**: Remove `unstable_renderSubtreeIntoContainer` [#28271](https://github.com/facebook/react/pull/28271) -- **react-dom**: Remove `unstable_runWithPrioirty` [#28271](https://github.com/facebook/react/pull/28271) +- **react-dom**: Remove `unstable_runWithPriority` [#28271](https://github.com/facebook/react/pull/28271) - **react-is**: Remove deprecated methods from `react-is` [28224](https://github.com/facebook/react/pull/28224) ### Other notable changes {/*other-notable-changes*/} @@ -734,7 +747,7 @@ const reducer = (state: State, action: Action) => state; - **react-dom**: Remove layout effect warning during SSR [#26395](https://github.com/facebook/react/pull/26395) - **react-dom**: Warn and donโ€™t set empty string for src/href (except anchor tags) [#28124](https://github.com/facebook/react/pull/28124) -We'll publish the full changelog with the stable release of React 19. +For a full list of changes, please see the [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md#1900-december-5-2024). --- diff --git a/src/content/blog/2024/05/22/react-conf-2024-recap.md b/src/content/blog/2024/05/22/react-conf-2024-recap.md index 96417fd8b..bc77f4bbb 100644 --- a/src/content/blog/2024/05/22/react-conf-2024-recap.md +++ b/src/content/blog/2024/05/22/react-conf-2024-recap.md @@ -17,7 +17,7 @@ Last week we hosted React Conf 2024, a two-day conference in Henderson, Nevada w --- -At React Conf 2024, we announced the [React 19 RC](/blog/2024/04/25/react-19), the [React Native New Architecture Beta](https://github.com/reactwg/react-native-new-architecture/discussions/189), and an experimental release of the [React Compiler](/learn/react-compiler). The community also took the stage to announce [React Router v7](https://remix.run/blog/merging-remix-and-react-router), [Universal Server Components](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=20765s) in Expo Router, React Server Components in [RedwoodJS](https://redwoodjs.com/blog/rsc-now-in-redwoodjs), and much more. +At React Conf 2024, we announced the [React 19 RC](/blog/2024/12/05/react-19), the [React Native New Architecture Beta](https://github.com/reactwg/react-native-new-architecture/discussions/189), and an experimental release of the [React Compiler](/learn/react-compiler). The community also took the stage to announce [React Router v7](https://remix.run/blog/merging-remix-and-react-router), [Universal Server Components](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=20765s) in Expo Router, React Server Components in [RedwoodJS](https://redwoodjs.com/blog/rsc-now-in-redwoodjs), and much more. The entire [day 1](https://www.youtube.com/watch?v=T8TZQ6k4SLE) and [day 2](https://www.youtube.com/watch?v=0ckOUBiuxVY) streams are available online. In this post, we'll summarize the talks and announcements from the event. @@ -36,7 +36,7 @@ For more, check out these talks from the community later in the conference: - [RedwoodJS, now with React Server Components](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=26815s) by [Amy Dutton](https://twitter.com/selfteachme) - [Introducing Universal React Server Components in Expo Router](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=20765s) by [Evan Bacon](https://twitter.com/Baconbrix) -Next in the keynote, [Josh Story](https://twitter.com/joshcstory) and [Andrew Clark](https://twitter.com/acdlite) shared new features coming in React 19, and announced the React 19 RC which is ready for testing in production. Check out all the features in the [React 19 release post](/blog/2024/04/25/react-19), and see these talks for deep dives on the new features: +Next in the keynote, [Josh Story](https://twitter.com/joshcstory) and [Andrew Clark](https://twitter.com/acdlite) shared new features coming in React 19, and announced the React 19 RC which is ready for testing in production. Check out all the features in the [React 19 release post](/blog/2024/12/05/react-19), and see these talks for deep dives on the new features: - [What's new in React 19](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=8880s) by [Lydia Hallie](https://twitter.com/lydiahallie) - [React Unpacked: A Roadmap to React 19](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=10112s) by [Sam Selikoff](https://twitter.com/samselikoff) diff --git a/src/content/blog/2024/10/21/react-compiler-beta-release.md b/src/content/blog/2024/10/21/react-compiler-beta-release.md new file mode 100644 index 000000000..f5a870b22 --- /dev/null +++ b/src/content/blog/2024/10/21/react-compiler-beta-release.md @@ -0,0 +1,126 @@ +--- +title: "React Compiler Beta Release" +author: Lauren Tan +date: 2024/10/21 +description: At React Conf 2024, we announced the experimental release of React Compiler, a build-time tool that optimizes your React app through automatic memoization. In this post, we want to share what's next for open source, and our progress on the compiler. + +--- + +October 21, 2024 by [Lauren Tan](https://twitter.com/potetotes). + +--- + + + +The React team is excited to share new updates: + + + +1. We're publishing React Compiler Beta today, so that early adopters and library maintainers can try it and provide feedback. +2. We're officially supporting React Compiler for apps on React 17+, through an optional `react-compiler-runtime` package. +3. We're opening up public membership of the [React Compiler Working Group](https://github.com/reactwg/react-compiler) to prepare the community for gradual adoption of the compiler. + +--- + +At [React Conf 2024](/blog/2024/05/22/react-conf-2024-recap), we announced the experimental release of React Compiler, a build-time tool that optimizes your React app through automatic memoization. [You can find an introduction to React Compiler here](/learn/react-compiler). + +Since the first release, we've fixed numerous bugs reported by the React community, received several high quality bug fixes and contributions[^1] to the compiler, made the compiler more resilient to the broad diversity of JavaScript patterns, and have continued to roll out the compiler more widely at Meta. + +In this post, we want to share what's next for React Compiler. + +## Try React Compiler Beta today {/*try-react-compiler-beta-today*/} + +At [React India 2024](https://www.youtube.com/watch?v=qd5yk2gxbtg), we shared an update on React Compiler. Today, we are excited to announce a new Beta release of React Compiler and ESLint plugin. New betas are published to npm using the `@beta` tag. + +To install React Compiler Beta: + + +npm install -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta + + +Or, if you're using Yarn: + + +yarn add -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta + + +You can watch [Sathya Gunasekaran's](https://twitter.com/_gsathya) talk at React India here: + + + +## We recommend everyone use the React Compiler linter today {/*we-recommend-everyone-use-the-react-compiler-linter-today*/} + +React Compilerโ€™s ESLint plugin helps developers proactively identify and correct [Rules of React](/reference/rules) violations. **We strongly recommend everyone use the linter today**. The linter does not require that you have the compiler installed, so you can use it independently, even if you are not ready to try out the compiler. + +To install the linter only: + + +npm install -D eslint-plugin-react-compiler@beta + + +Or, if you're using Yarn: + + +yarn add -D eslint-plugin-react-compiler@beta + + +After installation you can enable the linter by [adding it to your ESLint config](/learn/react-compiler#installing-eslint-plugin-react-compiler). Using the linter helps identify Rules of React breakages, making it easier to adopt the compiler when it's fully released. + +## Backwards Compatibility {/*backwards-compatibility*/} + +React Compiler produces code that depends on runtime APIs added in React 19, but we've since added support for the compiler to also work with React 17 and 18. If you are not on React 19 yet, in the Beta release you can now try out 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](/learn/react-compiler#using-react-compiler-with-react-17-or-18). + +## Using React Compiler in libraries {/*using-react-compiler-in-libraries*/} + +Our initial release was focused on identifying major issues with using the compiler in applications. We've gotten great feedback and have substantially improved the compiler since then. We're now ready for broad feedback from the community, and for library authors to try out the compiler to improve performance and the developer experience of maintaining your library. + +React Compiler can also be used to compile libraries. Because React Compiler needs to run on the original source code prior to any code transformations, it is not possible for an application's build pipeline to compile the libraries they use. Hence, our recommendation is for library maintainers to independently compile and test their libraries with the compiler, and ship compiled code to npm. + +Because your code is pre-compiled, users of your library will not need to have the compiler enabled in order to benefit from the automatic memoization applied to your library. If your library targets apps not yet on React 19, specify a minimum `target` and add `react-compiler-runtime` as a direct dependency. The runtime package will use the correct implementation of APIs depending on the application's version, and polyfill the missing APIs if necessary. + +[You can find more docs on this here.](/learn/react-compiler#using-the-compiler-on-libraries) + +## Opening up React Compiler Working Group to everyone {/*opening-up-react-compiler-working-group-to-everyone*/} + +We previously announced the invite-only [React Compiler Working Group](https://github.com/reactwg/react-compiler) at React Conf to provide feedback, ask questions, and collaborate on the compiler's experimental release. + +From today, together with the Beta release of React Compiler, we are opening up Working Group membership to everyone. The goal of the React Compiler Working Group is to prepare the ecosystem for a smooth, gradual adoption of React Compiler by existing applications and libraries. Please continue to file bug reports in the [React repo](https://github.com/facebook/react), but please leave feedback, ask questions, or share ideas in the [Working Group discussion forum](https://github.com/reactwg/react-compiler/discussions). + +The core team will also use the discussions repo to share our research findings. As the Stable Release gets closer, any important information will also be posted on this forum. + +## React Compiler at Meta {/*react-compiler-at-meta*/} + +At [React Conf](/blog/2024/05/22/react-conf-2024-recap), we shared that our rollout of the compiler on Quest Store and Instagram were successful. Since then, we've deployed React Compiler across several more major web apps at Meta, including [Facebook](https://www.facebook.com) and [Threads](https://www.threads.net). That means if you've used any of these apps recently, you may have had your experience powered by the compiler. We were able to onboard these apps onto the compiler with few code changes required, in a monorepo with more than 100,000 React components. + +We've seen notable performance improvements across all of these apps. As we've rolled out, we're continuing to see results on the order of [the wins we shared previously at ReactConf](https://youtu.be/lyEKhv8-3n0?t=3223). These apps have already been heavily hand tuned and optimized by Meta engineers and React experts over the years, so even improvements on the order of a few percent are a huge win for us. + +We also expected developer productivity wins from React Compiler. To measure this, we collaborated with our data science partners at Meta[^2] to conduct a thorough statistical analysis of the impact of manual memoization on productivity. Before rolling out the compiler at Meta, we discovered that only about 8% of React pull requests used manual memoization and that these pull requests took 31-46% longer to author[^3]. This confirmed our intuition that manual memoization introduces cognitive overhead, and we anticipate that React Compiler will lead to more efficient code authoring and review. Notably, React Compiler also ensures that *all* code is memoized by default, not just the (in our case) 8% where developers explicitly apply memoization. + +## Roadmap to Stable {/*roadmap-to-stable*/} + +*This is not a final roadmap, and is subject to change.* + +We intend to ship a Release Candidate of the compiler in the near future following the Beta release, when the majority of apps and libraries that follow the Rules of React have been proven to work well with the compiler. After a period of final feedback from the community, we plan on a Stable Release for the compiler. The Stable Release will mark the beginning of a new foundation for React, and all apps and libraries will be strongly recommended to use the compiler and ESLint plugin. + +* โœ… Experimental: Released at React Conf 2024, primarily for feedback from early adopters. +* โœ… Public Beta: Available today, for feedback from the wider community. +* ๐Ÿšง Release Candidate (RC): React Compiler works for the majority of rule-following apps and libraries without issue. +* ๐Ÿšง General Availability: After final feedback period from the community. + +These releases also include the compiler's ESLint plugin, which surfaces diagnostics statically analyzed by the compiler. We plan to combine the existing eslint-plugin-react-hooks plugin with the compiler's ESLint plugin, so only one plugin needs to be installed. + +Post-Stable, we plan to add more compiler optimizations and improvements. This includes both continual improvements to automatic memoization, and new optimizations altogether, with minimal to no change of product code. Upgrading to each new release of the compiler is aimed to be straightforward, and each upgrade will continue to improve performance and add better handling of diverse JavaScript and React patterns. + +Throughout this process, we also plan to prototype an IDE extension for React. It is still very early in research, so we expect to be able to share more of our findings with you in a future React Labs blog post. + +--- + +Thanks to [Sathya Gunasekaran](https://twitter.com/_gsathya), [Joe Savona](https://twitter.com/en_JS), [Ricky Hanlon](https://twitter.com/rickhanlonii), [Alex Taylor](https://github.com/alexmckenley), [Jason Bonta](https://twitter.com/someextent), and [Eli White](https://twitter.com/Eli_White) for reviewing and editing this post. + +--- + +[^1]: Thanks [@nikeee](https://github.com/facebook/react/pulls?q=is%3Apr+author%3Anikeee), [@henryqdineen](https://github.com/facebook/react/pulls?q=is%3Apr+author%3Ahenryqdineen), [@TrickyPi](https://github.com/facebook/react/pulls?q=is%3Apr+author%3ATrickyPi), and several others for their contributions to the compiler. + +[^2]: Thanks [Vaishali Garg](https://www.linkedin.com/in/vaishaligarg09) for leading this study on React Compiler at Meta, and for reviewing this post. + +[^3]: After controlling on author tenure, diff length/complexity, and other potential confounding factors. \ No newline at end of file diff --git a/src/content/blog/2024/04/25/react-19.md b/src/content/blog/2024/12/05/react-19.md similarity index 93% rename from src/content/blog/2024/04/25/react-19.md rename to src/content/blog/2024/12/05/react-19.md index 1b19c3546..9f212209b 100644 --- a/src/content/blog/2024/04/25/react-19.md +++ b/src/content/blog/2024/12/05/react-19.md @@ -1,21 +1,33 @@ --- -title: "React 19 RC" +title: "React v19" author: The React Team -date: 2024/04/25 -description: React 19 RC is now available on npm! In this post, we'll give an overview of the new features in React 19, and how you can adopt them. +date: 2024/12/05 +description: React 19 is now available on npm! In this post, we'll give an overview of the new features in React 19, and how you can adopt them. --- -April 25, 2024 by [The React Team](/community/team) +December 05, 2024 by [The React Team](/community/team) --- + + +### React 19 is now stable! {/*react-19-is-now-stable*/} + +Additions since this post was originally shared with the React 19 RC in April: + +- **Pre-warming for suspended trees**: see [Improvements to Suspense](/blog/2024/04/25/react-19-upgrade-guide#improvements-to-suspense). +- **React DOM static APIs**: see [New React DOM Static APIs](#new-react-dom-static-apis). + +_The date for this post has been update to reflect the stable release date._ + + -React 19 RC is now available on npm! +React v19 is now available on npm! -In our [React 19 RC Upgrade Guide](/blog/2024/04/25/react-19-upgrade-guide), we shared step-by-step instructions for upgrading your app to React 19. In this post, we'll give an overview of the new features in React 19, and how you can adopt them. +In our [React 19 Upgrade Guide](/blog/2024/04/25/react-19-upgrade-guide), we shared step-by-step instructions for upgrading your app to React 19. In this post, we'll give an overview of the new features in React 19, and how you can adopt them. - [What's new in React 19](#whats-new-in-react-19) - [Improvements in React 19](#improvements-in-react-19) @@ -312,6 +324,30 @@ The `use` API can only be called in render, similar to hooks. Unlike hooks, `use For more information, see the docs for [`use`](/reference/react/use). +## New React DOM Static APIs {/*new-react-dom-static-apis*/} + +We've added two new APIs to `react-dom/static` for static site generation: +- [`prerender`](/reference/react-dom/static/prerender) +- [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream) + +These new APIs improve on `renderToString` by waiting for data to load for static HTML generation. They are designed to work with streaming environments like Node.js Streams and Web Streams. For example, in a Web Stream environment, you can prerender a React tree to static HTML with `prerender`: + +```js +import { prerender } from 'react-dom/static'; + +async function handler(request) { + const {prelude} = await prerender(, { + bootstrapScripts: ['/main.js'] + }); + return new Response(prelude, { + headers: { 'content-type': 'text/html' }, + }); +} +``` + +Prerender APIs will wait for all data to load before returning the static HTML stream. Streams can be converted to strings, or sent with a streaming response. They do not support streaming content as it loads, which is supported by the existing [React DOM server rendering APIs](/reference/react-dom/server). + +For more information, see [React DOM Static APIs](/reference/react-dom/static). ## React Server Components {/*react-server-components*/} @@ -771,5 +807,4 @@ Thanks to [Joey Arhar](https://github.com/josepharhar) for driving the design an #### How to upgrade {/*how-to-upgrade*/} See the [React 19 Upgrade Guide](/blog/2024/04/25/react-19-upgrade-guide) for step-by-step instructions and a full list of breaking and notable changes. - - +_Note: this post was originally published 04/25/2024 and has been updated to 12/05/2024 with the stable release._ \ No newline at end of file diff --git a/src/content/blog/index.md b/src/content/blog/index.md index c70b1750a..da3907b3e 100644 --- a/src/content/blog/index.md +++ b/src/content/blog/index.md @@ -10,19 +10,25 @@ title: React ๋ธ”๋กœ๊ทธ
- + -Last week we hosted React Conf 2024, a two-day conference in Henderson, Nevada where 700+ attendees gathered in-person to discuss the latest in UI engineering. This was our first in-person conference since 2019, and we were thrilled to be able to bring the community together again ... +In the React 19 Upgrade Guide, we shared step-by-step instructions for upgrading your app to React 19. In this post, we'll give an overview of the new features in React 19, and how you can adopt them ... + + + + + +We announced an experimental release of React Compiler at React Conf 2024. We've made a lot of progress since then, and in this post we want to share what's next for React Compiler ... - + -In the React 19 RC Upgrade Guide, we shared step-by-step instructions for upgrading your app to React 19. In this post, we'll give an overview of the new features in React 19, and how you can adopt them ... +Last week we hosted React Conf 2024, a two-day conference in Henderson, Nevada where 700+ attendees gathered in-person to discuss the latest in UI engineering. This was our first in-person conference since 2019, and we were thrilled to be able to bring the community together again ... - + The improvements added to React 19 require some breaking changes, but we've worked to make the upgrade as smooth as possible, and we don't expect the changes to impact most apps. In this post, we will guide you through the steps for upgrading libraries to React 19 ... diff --git a/src/content/community/acknowledgements.md b/src/content/community/acknowledgements.md index 7edf63974..1f1d806e8 100644 --- a/src/content/community/acknowledgements.md +++ b/src/content/community/acknowledgements.md @@ -4,7 +4,11 @@ title: ๊ฐ์‚ฌ์˜ ๋ง +<<<<<<< HEAD React๋Š” ์›๋ž˜ [Jordan Walke](https://github.com/jordwalke)์— ์˜ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  React์—๋Š” [์ž‘์—…์„ ์ „๋‹ดํ•˜๋Š” ์ „์ž„ ํŒ€](/community/team)๊ณผ ์ฒœ์—ฌ ๋ช…์ด ๋„˜๋Š” [์˜คํ”ˆ ์†Œ์Šค ๊ธฐ์—ฌ์ž๋“ค](https://github.com/facebook/react/blob/main/AUTHORS)์ด ์žˆ์Šต๋‹ˆ๋‹ค. +======= +React was originally created by [Jordan Walke.](https://github.com/jordwalke) Today, React has a [dedicated full-time team working on it](/community/team), as well as over a thousand [open source contributors.](https://github.com/facebook/react/graphs/contributors) +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 diff --git a/src/content/community/team.md b/src/content/community/team.md index 6004476e2..b11925407 100644 --- a/src/content/community/team.md +++ b/src/content/community/team.md @@ -18,7 +18,7 @@ Current members of the React team are listed in alphabetical order below. Andrew got started with web development by making sites with WordPress, and eventually tricked himself into doing JavaScript. His favorite pastime is karaoke. Andrew is either a Disney villain or a Disney princess, depending on the day. - + Dan got into programming after he accidentally discovered Visual Basic inside Microsoft PowerPoint. He has found his true calling in turning [Sebastian](#sebastian-markbรฅge)'s tweets into long-form blog posts. Dan occasionally wins at Fortnite by hiding in a bush until the game ends. @@ -38,11 +38,11 @@ Current members of the React team are listed in alphabetical order below. Joe was planning to major in math and philosophy but got into computer science after writing physics simulations in Matlab. Prior to React, he worked on Relay, RSocket.js, and the Skip programming language. While heโ€™s not building some sort of reactive system he enjoys running, studying Japanese, and spending time with his family. - + Josh majored in Mathematics and discovered programming while in college. His first professional developer job was to program insurance rate calculations in Microsoft Excel, the paragon of Reactive Programming which must be why he now works on React. In between that time Josh has been an IC, Manager, and Executive at a few startups. outside of work he likes to push his limits with cooking. - + Lauren's programming career peaked when she first discovered the `` tag. Sheโ€™s been chasing that high ever since. She studied Finance instead of CS in college, so she learned to code using Excel instead of Java. Lauren enjoys dropping cheeky memes in chat, playing video games with her partner, and petting her dog Zelda. @@ -62,7 +62,7 @@ Current members of the React team are listed in alphabetical order below. Noahโ€™s interest in UI programming sparked during his education in music technology at NYU. At Meta, he's worked on internal tools, browsers, web performance, and is currently focused on React. Outside of work, Noah can be found tinkering with synthesizers or spending time with his cat. - + Ricky majored in theoretical math and somehow found himself on the React Native team for a couple years before joining the React team. When he's not programming you can find him snowboarding, biking, climbing, golfing, or closing GitHub issues that do not match the issue template. diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index 7a8a5bf73..b3f3d24e2 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -256,11 +256,11 @@ export default function CatFriends() { key={cat} ref={(node) => { const map = getMap(); - if (node) { - map.set(cat, node); - } else { + map.set(cat, node); + + return () => { map.delete(cat); - } + }; }} > @@ -309,16 +309,6 @@ li { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "^5.0.0" - } -} -``` - ์ด ์˜ˆ์‹œ์—์„œ `itemsRef`๋Š” ํ•˜๋‚˜์˜ DOM ๋…ธ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹ ์— ์‹๋ณ„์ž์™€ DOM ๋…ธ๋“œ๋กœ ์—ฐ๊ฒฐ๋œ [Map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ([Ref๋Š” ์–ด๋–ค ๊ฐ’์ด๋“  ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!](/learn/referencing-values-with-refs)) ๋ชจ๋“  ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์— ์žˆ๋Š” [`ref` ์ฝœ๋ฐฑ](/reference/react-dom/components/common#ref-callback)์€ Map ๋ณ€๊ฒฝ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. @@ -328,6 +318,7 @@ li { key={cat.id} ref={node => { const map = getMap(); +<<<<<<< HEAD if (node) { // Map์— ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค map.set(cat, node); @@ -350,6 +341,8 @@ This example shows another approach for managing the Map with a `ref` callback c key={cat.id} ref={node => { const map = getMap(); +======= +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 // Add to the Map map.set(cat, node); @@ -361,7 +354,15 @@ This example shows another approach for managing the Map with a `ref` callback c > ``` - +This lets you read individual DOM nodes from the Map later. + + + +When Strict Mode is enabled, ref callbacks will run twice in development. + +Read more about [how this helps find bugs](/reference/react/StrictMode#fixing-bugs-found-by-re-running-ref-callbacks-in-development) in callback refs. + + diff --git a/src/content/learn/react-compiler.md b/src/content/learn/react-compiler.md index 588b2f071..4ce611363 100644 --- a/src/content/learn/react-compiler.md +++ b/src/content/learn/react-compiler.md @@ -3,7 +3,11 @@ title: React ์ปดํŒŒ์ผ๋Ÿฌ --- +<<<<<<< HEAD ์ด ํŽ˜์ด์ง€๋Š” ์ƒˆ๋กœ์šด ์‹คํ—˜์  React ์ปดํŒŒ์ผ๋Ÿฌ์— ๋Œ€ํ•œ ์†Œ๊ฐœ์™€ ์ด๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์‹œ๋„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +======= +This page will give you an introduction to React Compiler and how to try it out successfully. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 @@ -12,13 +16,20 @@ title: React ์ปดํŒŒ์ผ๋Ÿฌ +<<<<<<< HEAD * ์ปดํŒŒ์ผ๋Ÿฌ ์‹œ์ž‘ํ•˜๊ธฐ * ์ปดํŒŒ์ผ๋Ÿฌ ๋ฐ eslint ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜ * ๋ฌธ์ œ ํ•ด๊ฒฐ +======= +* Getting started with the compiler +* Installing the compiler and ESLint plugin +* Troubleshooting +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 +<<<<<<< HEAD React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ๋กœ๋ถ€ํ„ฐ ์ดˆ๊ธฐ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ์˜คํ”ˆ์†Œ์Šค๋กœ ๊ณต๊ฐœํ•œ ์ƒˆ๋กœ์šด ์‹คํ—˜์  ์ปดํŒŒ์ผ๋Ÿฌ์ž…๋‹ˆ๋‹ค. ์•„์ง ์•ˆ์ •์ ์ด์ง€ ์•Š์œผ๋ฉฐ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์™„์ „ํžˆ ์ค€๋น„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” React 19 RC๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. React 19๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ [์›Œํ‚น ๊ทธ๋ฃน](https://github.com/reactwg/react-compiler/discussions/6)์— ์„ค๋ช…๋œ ๋Œ€๋กœ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ์บ์‹œ ํ•จ์ˆ˜ ๊ตฌํ˜„์„ ์‹œ๋„ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ๋ฐฉ๋ฒ•์€ ๊ถŒ์žฅํ•˜์ง€ ์•Š์œผ๋ฉฐ ๊ฐ€๋Šฅํ•œ ํ•œ React 19๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. @@ -27,6 +38,30 @@ React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” React 19 RC๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. React 19๋กœ ์—…๊ทธ๋ ˆ React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋นŒ๋“œ ํƒ€์ž„ ์ „์šฉ ๋„๊ตฌ๋กœ React ์•ฑ์„ ์ž๋™์œผ๋กœ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ˆœ์ˆ˜ JavaScript๋กœ ๋™์ž‘ํ•˜๋ฉฐ [React์˜ ๊ทœ์น™](/reference/rules)์„ ์ดํ•ดํ•˜๋ฏ€๋กœ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ์—๋Š” ์—๋””ํ„ฐ ๋‚ด์—์„œ ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” [eslint ํ”Œ๋Ÿฌ๊ทธ์ธ](#installing-eslint-plugin-react-compiler)๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ปดํŒŒ์ผ๋Ÿฌ์™€ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉฐ, ์•ฑ์—์„œ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  React ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ฝ”๋“œ๋ฒ ์ด์Šค์˜ ํ’ˆ์งˆ์„ ํ–ฅ์ƒํ•˜๊ธฐ ์œ„ํ•ด ์ด eslint ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. +======= +React Compiler is a new compiler currently in Beta, that we've open sourced to get early feedback from the community. While it has been used in production at companies like Meta, rolling out the compiler to production for your app will depend on the health of your codebase and how well youโ€™ve followed the [Rules of React](/reference/rules). + +The latest Beta release can be found with the `@beta` tag, and daily experimental releases with `@experimental`. + + +React Compiler is a new compiler that we've open sourced to get early feedback from the community. It is a build-time only tool that automatically optimizes your React app. It works with plain JavaScript, and understands the [Rules of React](/reference/rules), so you don't need to rewrite any code to use it. + +The compiler also includes an [ESLint plugin](#installing-eslint-plugin-react-compiler) that surfaces the analysis from the compiler right in your editor. **We strongly recommend everyone use the linter today.** The linter does not require that you have the compiler installed, so you can use it even if you are not ready to try out the compiler. + +The compiler is currently released as `beta`, and is available to try out on React 17+ apps and libraries. To install the Beta: + + +npm install -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta + + +Or, if you're using Yarn: + + +yarn add -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta + + +If you are not using React 19 yet, please see [the section below](#using-react-compiler-with-react-17-or-18) for further instructions. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ### ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฌด์—‡์„ ํ•˜๋‚˜์š”? {/*what-does-the-compiler-do*/} @@ -34,7 +69,15 @@ React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ์ž ์ปดํŒŒ์ผ๋Ÿฌ๋Š” JavaScript์™€ React์˜ ๊ทœ์น™์— ๋Œ€ํ•œ ์ง€์‹์„ ํ™œ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์™€ Hooks ๋‚ด์˜ ๊ฐ’ ๋˜๋Š” ๊ฐ’ ๊ทธ๋ฃน์„ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํ•ฉ๋‹ˆ๋‹ค. ๊ทœ์น™ ์œ„๋ฐ˜์„ ๊ฐ์ง€ํ•  ๊ฒฝ์šฐ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ ๋˜๋Š” Hooks๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ปดํŒŒ์ผํ•ฉ๋‹ˆ๋‹ค. +<<<<<<< HEAD ์ด๋ฏธ ์ฝ”๋“œ๋ฒ ์ด์Šค์— ๋ฉ”๋ชจ์ด์ œ์ด์…˜์ด ์ž˜ ๋˜์–ด ์žˆ๋‹ค๋ฉด, ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ํ†ตํ•ด ์ฃผ์š” ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ๊ธฐ๋Œ€ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ๋กœ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ์˜ฌ๋ฐ”๋ฅธ ์˜์กด์„ฑ์„ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํ•˜๋Š” ๊ฒƒ์€ ์ˆ˜์ž‘์—…์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= + +React Compiler can statically detect when Rules of React are broken, and safely opt-out of optimizing just the affected components or hooks. It is not necessary for the compiler to optimize 100% of your codebase. + + +If your codebase is already very well-memoized, you might not expect to see major performance improvements with the compiler. However, in practice memoizing the correct dependencies that cause performance issues is tricky to get right by hand. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 #### React Compiler์€ ์–ด๋–ค ๊ฒƒ์„ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํ•˜๋‚˜์š”? {/*what-kind-of-memoization-does-react-compiler-add*/} @@ -96,6 +139,7 @@ function TableContainer({ items }) { ๋”ฐ๋ผ์„œ `expensivelyProcessAReallyLargeArrayOfObjects`๊ฐ€ ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค๋ฉด ๋™์ผํ•œ ์•„์ดํ…œ์ด ์ „๋‹ฌ๋˜๋”๋ผ๋„ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๊ณ„์‚ฐ์ด ๋ฐ˜๋ณต์ ์œผ๋กœ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์ „์— ๋จผ์ € [ํ”„๋กœํŒŒ์ผ๋ง](https://ko.react.dev/reference/react/useMemo#how-to-tell-if-a-calculation-is-expensive)์„ ํ†ตํ•ด ํ•ด๋‹น ๊ณ„์‚ฐ์ด ์‹ค์ œ๋กœ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +<<<<<<< HEAD ### ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฌด์—‡์„ ๊ฐ€์ •ํ•˜๋‚˜์š”? {/*what-does-the-compiler-assume*/} React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. @@ -109,6 +153,11 @@ React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” React์˜ ๋งŽ์€ ๊ทœ์น™์„ ์ •์ ์œผ๋กœ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ ### ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‹œ๋„ํ•ด ๋ด์•ผ ํ•˜๋‚˜์š”? {/*should-i-try-out-the-compiler*/} ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์—ฌ์ „ํžˆ ์‹คํ—˜์ ์ด๋ฉฐ ๋‹ค์–‘ํ•œ ๊ฒฐํ•จ์ด ์žˆ๋‹ค๋Š” ์ ์„ ์œ ์˜ํ•˜์„ธ์š”. Meta์™€ ๊ฐ™์€ ํšŒ์‚ฌ์—์„œ๋Š” ์ด๋ฏธ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜์˜€์ง€๋งŒ, ์•ฑ์˜ ํ”„๋กœ๋•์…˜์— ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์ ์ง„์ ์œผ๋กœ ๋„์ž…ํ• ์ง€๋Š” ์ฝ”๋“œ๋ฒ ์ด์Šค์˜ ๊ฑด๊ฐ• ์ƒํƒœ์™€ [React์˜ ๊ทœ์น™](/reference/rules)์„ ์–ผ๋งˆ๋‚˜ ์ž˜ ๋”ฐ๋ž๋Š”์ง€์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +======= +### Should I try out the compiler? {/*should-i-try-out-the-compiler*/} + +Please note that the compiler is still in Beta and has many rough edges. While it has been used in production at companies like Meta, rolling out the compiler to production for your app will depend on the health of your codebase and how well you've followed the [Rules of React](/reference/rules). +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 **์ง€๊ธˆ ๋‹น์žฅ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์— ๊ธ‰๊ธ‰ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์•ˆ์ •์ ์ธ ๋ฆด๋ฆฌ์ฆˆ์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.** ํ•˜์ง€๋งŒ ์•ฑ์—์„œ ์ž‘์€ ์‹คํ—˜์„ ํ†ตํ•ด ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‹œ๋„ํ•ด ๋ณด๊ณ  [ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณต](#reporting-issues)ํ•˜์—ฌ ์ปดํŒŒ์ผ๋Ÿฌ ๊ฐœ์„ ์— ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -116,6 +165,7 @@ React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” React์˜ ๋งŽ์€ ๊ทœ์น™์„ ์ •์ ์œผ๋กœ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ ์ด ๋ฌธ์„œ ์™ธ์—๋„ [React ์ปดํŒŒ์ผ๋Ÿฌ ์›Œํ‚น ๊ทธ๋ฃน](https://github.com/reactwg/react-compiler)์„ ํ™•์ธํ•˜์—ฌ ์ปดํŒŒ์ผ๋Ÿฌ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด์™€ ๋…ผ์˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. +<<<<<<< HEAD ### ํ˜ธํ™˜์„ฑ ํ™•์ธ {/*checking-compatibility*/} ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์„ค์น˜ํ•˜๊ธฐ ์ „์—, ๋จผ์ € ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ ํ˜ธํ™˜๋˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -141,12 +191,38 @@ Found no usage of incompatible libraries. ### `eslint-plugin-react-compiler` ์„ค์น˜ {/*installing-eslint-plugin-react-compiler*/} React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” eslint ํ”Œ๋Ÿฌ๊ทธ์ธ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. eslint ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ปดํŒŒ์ผ๋Ÿฌ์™€ **๋…๋ฆฝ์ ์œผ๋กœ** ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ eslint ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= +### Installing eslint-plugin-react-compiler {/*installing-eslint-plugin-react-compiler*/} + +React Compiler also powers an ESLint plugin. The ESLint plugin can be used **independently** of the compiler, meaning you can use the ESLint plugin even if you don't use the compiler. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 -npm install eslint-plugin-react-compiler@experimental +npm install -D eslint-plugin-react-compiler@beta +<<<<<<< HEAD ๊ทธ๋Ÿฐ ๋‹ค์Œ, eslint ๊ตฌ์„ฑ ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•˜์„ธ์š”. +======= +Then, add it to your ESLint config: + +```js +import reactCompiler from 'eslint-plugin-react-compiler' + +export default [ + { + plugins: { + 'react-compiler': reactCompiler, + }, + rules: { + 'react-compiler/react-compiler': 'error', + }, + }, +] +``` + +Or, in the deprecated eslintrc config format: +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ```js module.exports = { @@ -154,14 +230,22 @@ module.exports = { 'eslint-plugin-react-compiler', ], rules: { - 'react-compiler/react-compiler': "error", + 'react-compiler/react-compiler': 'error', }, } ``` +<<<<<<< HEAD eslint ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์—๋””ํ„ฐ์—์„œ React ๊ทœ์น™ ์œ„๋ฐ˜ ์‚ฌํ•ญ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋‚˜ Hook์˜ ์ตœ์ ํ™”๋ฅผ ๊ฑด๋„ˆ๋›ฐ์—ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์ •์ƒ์ ์ธ ๋™์ž‘์ด๋ฉฐ, ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด๋ฅผ ๋ณต๊ตฌํ•˜๊ณ  ์ฝ”๋“œ๋ฒ ์ด์Šค์˜ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ณ„์†ํ•ด์„œ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. **๋ชจ๋“  eslint ์œ„๋ฐ˜ ์‚ฌํ•ญ์„ ์ฆ‰์‹œ ์ˆ˜์ •ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.** ์ž์‹ ์˜ ์†๋„์— ๋งž์ถฐ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ์ตœ์ ํ™”๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์™€ Hooks์˜ ์ˆ˜๋ฅผ ๋Š˜๋ฆด ์ˆ˜ ์žˆ์ง€๋งŒ, ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๋ชจ๋“  ๊ฒƒ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. +======= +The ESLint plugin will display any violations of the rules of React in your editor. When it does this, it means that the compiler has skipped over optimizing that component or hook. This is perfectly okay, and the compiler can recover and continue optimizing other components in your codebase. + + +**You don't have to fix all ESLint violations straight away.** You can address them at your own pace to increase the amount of components and hooks being optimized, but it is not required to fix everything before you can use the compiler. + +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ### ์ฝ”๋“œ๋ฒ ์ด์Šค์— ์ปดํŒŒ์ผ๋Ÿฌ ์ ์šฉํ•˜๊ธฐ {/*using-the-compiler-effectively*/} @@ -178,6 +262,7 @@ const ReactCompilerConfig = { }; ``` +<<<<<<< HEAD ๋“œ๋ฌผ์ง€๋งŒ ๋•Œ์— ๋”ฐ๋ผ์„œ๋Š” `compilationMode: "annotation"` ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ "opt-in" ๋ชจ๋“œ๋กœ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ชจ๋“œ์—์„œ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ `"use memo"` ์ง€์‹œ์–ด๋กœ ์ฃผ์„ ์ฒ˜๋ฆฌ๋œ ์ปดํฌ๋„ŒํŠธ์™€ Hooks๋งŒ ์ปดํŒŒ์ผํ•ฉ๋‹ˆ๋‹ค. `annotation` ๋ชจ๋“œ๋Š” ์ดˆ๊ธฐ ์‚ฌ์šฉ์ž๋ฅผ ๋•๊ธฐ ์œ„ํ•œ ์ž„์‹œ ๋ชจ๋“œ๋กœ, `"use memo"` ์ง€์‹œ์–ด๋ฅผ ์žฅ๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์˜๋„๋Š” ์—†์Œ์„ ์œ ์˜ํ•˜์„ธ์š”. ```js {2,7} @@ -193,62 +278,81 @@ export default function App() { ``` ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ๋„์ž…ํ•˜๋Š” ๋ฐ ๋” ์ž์‹ ๊ฐ์„ ๊ฐ€์ง€๊ฒŒ ๋˜๋ฉด, ๋‹ค๋ฅธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋Œ€ํ•œ ์ปค๋ฒ„๋ฆฌ์ง€๋ฅผ ํ™•๋Œ€ํ•˜๊ณ  ์ ์ง„์ ์œผ๋กœ ์ „์ฒด ์•ฑ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= +When you have more confidence with rolling out the compiler, you can expand coverage to other directories as well and slowly roll it out to your whole app. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 #### ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ {/*new-projects*/} ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•  ๊ฒฝ์šฐ, ๊ธฐ๋ณธ ๋™์ž‘์œผ๋กœ ์ „์ฒด ์ฝ”๋“œ๋ฒ ์ด์Šค์— ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +<<<<<<< HEAD ## ์‚ฌ์šฉ ๋ฐฉ๋ฒ• {/*installation*/} +======= +### Using React Compiler with React 17 or 18 {/*using-react-compiler-with-react-17-or-18*/} -### Babel {/*usage-with-babel*/} +React Compiler works best with React 19 RC. If you are unable to upgrade, you can install the extra `react-compiler-runtime` package which will allow the compiled code to run on versions prior to 19. However, note that the minimum supported version is 17. -npm install babel-plugin-react-compiler@experimental +npm install react-compiler-runtime@beta -์ปดํŒŒ์ผ๋Ÿฌ์—๋Š” ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Babel ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. - -์„ค์น˜ ํ›„์— Babel ๊ตฌ์„ฑ ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•˜์„ธ์š”. ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ **๋จผ์ €** ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. +You should also add the correct `target` to your compiler config, where `target` is the major version of React you are targeting: -```js {7} +```js {3} // babel.config.js -const ReactCompilerConfig = { /* ... */ }; +const ReactCompilerConfig = { + target: '18' // '17' | '18' | '19' +}; module.exports = function () { return { plugins: [ - ['babel-plugin-react-compiler', ReactCompilerConfig], // ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰ํ•˜์„ธ์š”! - // ... + ['babel-plugin-react-compiler', ReactCompilerConfig], ], }; }; ``` -`babel-plugin-react-compiler`๋Š” ๋‹ค๋ฅธ Babel ํ”Œ๋Ÿฌ๊ทธ์ธ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์‚ฌ์šด๋“œ ๋ถ„์„(sound analysis)์„ ์œ„ํ•ด ์ž…๋ ฅ ์†Œ์Šค ์ •๋ณด๋ฅผ ํ•„์š”๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +### Using the compiler on libraries {/*using-the-compiler-on-libraries*/} -React Compiler works best with React 19 RC. If you are unable to upgrade, you can install the extra `react-compiler-runtime` package which will allow the compiled code to run on versions prior to 19. However, note that the minimum supported version is 17. +React Compiler can also be used to compile libraries. Because React Compiler needs to run on the original source code prior to any code transformations, it is not possible for an application's build pipeline to compile the libraries they use. Hence, our recommendation is for library maintainers to independently compile and test their libraries with the compiler, and ship compiled code to npm. + +Because your code is pre-compiled, users of your library will not need to have the compiler enabled in order to benefit from the automatic memoization applied to your library. If your library targets apps not yet on React 19, specify a minimum [`target` and add `react-compiler-runtime` as a direct dependency](#using-react-compiler-with-react-17-or-18). The runtime package will use the correct implementation of APIs depending on the application's version, and polyfill the missing APIs if necessary. + +Library code can often require more complex patterns and usage of escape hatches. For this reason, we recommend ensuring that you have sufficient testing in order to identify any issues that might arise from using the compiler on your library. If you identify any issues, you can always opt-out the specific components or hooks with the [`'use no memo'` directive](#something-is-not-working-after-compilation). + +Similarly to apps, it is not necessary to fully compile 100% of your components or hooks to see benefits in your library. A good starting point might be to identify the most performance sensitive parts of your library and ensuring that they don't break the [Rules of React](/reference/rules), which you can use `eslint-plugin-react-compiler` to identify. + +## Usage {/*installation*/} +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 + +### Babel {/*usage-with-babel*/} -npm install react-compiler-runtime@experimental +npm install babel-plugin-react-compiler@beta -You should also add the correct `target` to your compiler config, where `target` is the major version of React you are targeting: +์ปดํŒŒ์ผ๋Ÿฌ์—๋Š” ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Babel ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. -```js {3} +์„ค์น˜ ํ›„์— Babel ๊ตฌ์„ฑ ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•˜์„ธ์š”. ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ **๋จผ์ €** ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. + +```js {7} // babel.config.js -const ReactCompilerConfig = { - target: '18' // '17' | '18' | '19' -}; +const ReactCompilerConfig = { /* ... */ }; module.exports = function () { return { plugins: [ - ['babel-plugin-react-compiler', ReactCompilerConfig], + ['babel-plugin-react-compiler', ReactCompilerConfig], // ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰ํ•˜์„ธ์š”! + // ... ], }; }; ``` +`babel-plugin-react-compiler`๋Š” ๋‹ค๋ฅธ Babel ํ”Œ๋Ÿฌ๊ทธ์ธ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์‚ฌ์šด๋“œ ๋ถ„์„(sound analysis)์„ ์œ„ํ•ด ์ž…๋ ฅ ์†Œ์Šค ์ •๋ณด๋ฅผ ํ•„์š”๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + ### Vite {/*usage-with-vite*/} Vite๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, `vite-plugin-react`์— ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -275,6 +379,7 @@ export default defineConfig(() => { ### Next.js {/*usage-with-nextjs*/} +<<<<<<< HEAD Next.js์—๋Š” React ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋Š” ์‹คํ—˜์ ์ธ ๊ตฌ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ตฌ์„ฑ์€ ์ž๋™์œผ๋กœ Babel์ด `babel-plugin-react-compiler`์™€ ํ•จ๊ป˜ ์„ค์ •๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. - React 19 ๋ฆด๋ฆฌ์ฆˆ ํ›„๋ณด ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋Š” Next.js ์นด๋‚˜๋ฆฌ(Canary) ๋ฒ„์ „์„ ์„ค์น˜ํ•˜์„ธ์š”. @@ -305,6 +410,9 @@ module.exports = nextConfig; - Webpack (๊ธฐ๋ณธ) - Turbopack (`--turbo` ์˜ต์…˜์„ ํ†ตํ•ด ํ™œ์„ฑํ™”) +======= +Please refer to the [Next.js docs](https://nextjs.org/docs/app/api-reference/next-config-js/reactCompiler) for more information. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ### Remix {/*usage-with-remix*/} `vite-plugin-babel`์„ ์„ค์น˜ํ•˜๊ณ  ์ปดํŒŒ์ผ๋Ÿฌ์˜ Babel ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”. @@ -337,6 +445,7 @@ export default defineConfig({ ### Webpack {/*usage-with-webpack*/} +<<<<<<< HEAD ๋‹ค์Œ๊ณผ ๊ฐ™์ด React ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์œ„ํ•œ ์ž์ฒด ๋กœ๋”๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```js @@ -375,6 +484,13 @@ module.exports = reactCompilerLoader; ### Expo {/*usage-with-expo*/} Expo ์•ฑ์—์„œ React Compiler ๋ฅผ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” [Expo's docs](https://docs.expo.dev/preview/react-compiler/) ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”. +======= +A community Webpack loader is [now available here](https://github.com/SukkaW/react-compiler-webpack). + +### Expo {/*usage-with-expo*/} + +Please refer to [Expo's docs](https://docs.expo.dev/guides/react-compiler/) to enable and use the React Compiler in Expo apps. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ### Metro (React Native) {/*usage-with-react-native-metro*/} @@ -394,22 +510,43 @@ Rsbuild ์•ฑ์—์„œ React Compiler ๋ฅผ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” [ React ์ปดํŒŒ์ผ๋Ÿฌ ์›Œํ‚น ๊ทธ๋ฃน์—์„œ๋„ ํšŒ์›์œผ๋กœ ์‹ ์ฒญํ•˜์—ฌ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. [๊ฐ€์ž…์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ README](https://github.com/reactwg/react-compiler)์—์„œ ํ™•์ธํ•˜์„ธ์š”. +<<<<<<< HEAD ### `(0 , _c) is not a function` ์—๋Ÿฌ {/*0--_c-is-not-a-function-error*/} ์ด ์—๋Ÿฌ๋Š” React 19 RC ์ด์ƒ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ๋จผ์ € [React 19 RC๋กœ ์•ฑ์„ ์—…๊ทธ๋ ˆ์ด๋“œ](https://ko.react.dev/blog/2024/04/25/react-19-upgrade-guide)ํ•˜์„ธ์š”. React 19๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, [์›Œํ‚น ๊ทธ๋ฃน](https://github.com/reactwg/react-compiler/discussions/6)์—์„œ ์„ค๋ช…ํ•œ ๋Œ€๋กœ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ์บ์‹œ ํ•จ์ˆ˜ ๊ตฌํ˜„์„ ์‹œ๋„ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ€๋Šฅํ•˜๋ฉด React 19๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. +======= +### What does the compiler assume? {/*what-does-the-compiler-assume*/} + +React Compiler assumes that your code: + +1. Is valid, semantic JavaScript. +2. Tests that nullable/optional values and properties are defined before accessing them (for example, by enabling [`strictNullChecks`](https://www.typescriptlang.org/tsconfig/#strictNullChecks) if using TypeScript), i.e., `if (object.nullableProperty) { object.nullableProperty.foo }` or with optional-chaining `object.nullableProperty?.foo`. +3. Follows the [Rules of React](https://react.dev/reference/rules). + +React Compiler can verify many of the Rules of React statically, and will safely skip compilation when it detects an error. To see the errors we recommend also installing [eslint-plugin-react-compiler](https://www.npmjs.com/package/eslint-plugin-react-compiler). +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ### ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ตœ์ ํ™”๋˜์—ˆ๋Š”์ง€ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์„๊นŒ์š”? {/*how-do-i-know-my-components-have-been-optimized*/} [React Devtools](/learn/react-developer-tools) (v5.0+)์—๋Š” React ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ๋‚ด์žฅ ์ง€์›ํ•˜๋ฉฐ, ์ปดํŒŒ์ผ๋Ÿฌ์— ์˜ํ•ด ์ตœ์ ํ™”๋œ ์ปดํฌ๋„ŒํŠธ ์˜†์— "Memo โœจ" ๋ฐฐ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. +<<<<<<< HEAD ### ์ปดํŒŒ์ผ ํ›„ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ {/*something-is-not-working-after-compilation*/} `eslint-plugin-react-compiler`์„ ์„ค์น˜ํ•œ ๊ฒฝ์šฐ, ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์—๋””ํ„ฐ์—์„œ React ๊ทœ์น™ ์œ„๋ฐ˜ ์‚ฌํ•ญ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋‚˜ Hook์˜ ์ตœ์ ํ™”๋ฅผ ๊ฑด๋„ˆ๋›ฐ์—ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์ •์ƒ์ ์ธ ๋™์ž‘์ด๋ฉฐ, ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด๋ฅผ ๋ณต๊ตฌํ•˜๊ณ  ์ฝ”๋“œ๋ฒ ์ด์Šค์˜ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ณ„์†ํ•ด์„œ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. **๋ชจ๋“  eslint ์œ„๋ฐ˜ ์‚ฌํ•ญ์„ ์ฆ‰์‹œ ์ˆ˜์ •ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.** ์ž์‹ ์˜ ์†๋„์— ๋งž์ถฐ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ์ตœ์ ํ™”๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์™€ Hooks์˜ ์ˆ˜๋ฅผ ์ ์ง„์ ์œผ๋กœ ๋Š˜๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= +### Something is not working after compilation {/*something-is-not-working-after-compilation*/} +If you have eslint-plugin-react-compiler installed, the compiler will display any violations of the rules of React in your editor. When it does this, it means that the compiler has skipped over optimizing that component or hook. This is perfectly okay, and the compiler can recover and continue optimizing other components in your codebase. **You don't have to fix all ESLint violations straight away.** You can address them at your own pace to increase the amount of components and hooks being optimized. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ๊ทธ๋Ÿฌ๋‚˜ JavaScript์˜ ์œ ์—ฐํ•˜๊ณ  ๋™์ ์ธ ํŠน์„ฑ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๊ฒฝ์šฐ๋ฅผ ์ฒ ์ €ํ•˜๊ฒŒ ๊ฐ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌ๋ฉด ๋ฒ„๊ทธ๋‚˜ ๋ฌดํ•œ ๋ฃจํ”„์™€ ๊ฐ™์€ ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +<<<<<<< HEAD ์ปดํŒŒ์ผ ํ›„ ์•ฑ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ  eslint ์—๋Ÿฌ๋„ ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ž˜๋ชป ์ปดํŒŒ์ผํ•œ ๊ฒƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ๊ด€๋ จ๋œ ์ปดํฌ๋„ŒํŠธ๋‚˜ Hook์„ [`"use no memo"` ์ง€์‹œ์–ด](#opt-out-of-the-compiler-for-a-component)๋ฅผ ํ†ตํ•ด ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ œ์™ธํ•ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ์‹œ๋„ํ•ด ๋ณด์„ธ์š”. +======= +If your app doesn't work properly after compilation and you aren't seeing any ESLint errors, the compiler may be incorrectly compiling your code. To confirm this, try to make the issue go away by aggressively opting out any component or hook you think might be related via the [`"use no memo"` directive](#opt-out-of-the-compiler-for-a-component). +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ```js {2} function SuspiciousComponent() { diff --git a/src/content/learn/react-developer-tools.md b/src/content/learn/react-developer-tools.md index 1981b78af..06f532fd3 100644 --- a/src/content/learn/react-developer-tools.md +++ b/src/content/learn/react-developer-tools.md @@ -52,6 +52,7 @@ react-devtools ![React Developer Tools standalone](/images/docs/react-devtools-standalone.png) +<<<<<<< HEAD ## ๋ชจ๋ฐ”์ผ (React Native) {/*mobile-react-native*/} React Developer Tools๋Š” [React Native](https://reactnative.dev/)๋กœ ๋งŒ๋“ค์–ด์ง„ ์•ฑ์—์„œ๋„ ์ž˜ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. @@ -59,11 +60,15 @@ React Developer Tools๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ์ „์—ญ์ ์œผ๋กœ ```bash # Yarn yarn global add react-devtools +======= +## Mobile (React Native) {/*mobile-react-native*/} -# Npm -npm install -g react-devtools -``` +To inspect apps built with [React Native](https://reactnative.dev/), you can use [React Native DevTools](https://reactnative.dev/docs/debugging/react-native-devtools), the built-in debugger that deeply integrates React Developer Tools. All features work identically to the browser extension, including native element highlighting and selection. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 + +[Learn more about debugging in React Native.](https://reactnative.dev/docs/debugging) +<<<<<<< HEAD ๋‹ค์Œ์œผ๋กœ ํ„ฐ๋ฏธ๋„์—์„œ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ์—ฌ์‹ญ์‹œ์˜ค. ```bash react-devtools @@ -74,3 +79,6 @@ react-devtools > ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๊ฐ€ ๋ช‡ ์ดˆ ํ›„์— ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์œผ๋ฉด ์•ฑ์„ ๋‹ค์‹œ ๋กœ๋“œํ•ด ๋ณด์‹ญ์‹œ์˜ค. [React Native ๋””๋ฒ„๊น…์— ๋Œ€ํ•˜์—ฌ ๋” ์•Œ์•„๋ณด๊ธฐ](https://reactnative.dev/docs/debugging) +======= +> For versions of React Native earlier than 0.76, please use the standalone build of React DevTools by following the [Safari and other browsers](#safari-and-other-browsers) guide above. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index 439792948..8ce1a5536 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -44,10 +44,17 @@ root.render(); * **optional** `options`: React ๋ฃจํŠธ์— ๋Œ€ํ•œ ์˜ต์…˜์„ ๊ฐ€์ง„ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. +<<<<<<< HEAD * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`. * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown, and an `errorInfo` object containing the `componentStack`. * **optional** `onRecoverableError`: React๊ฐ€ ์˜ค๋ฅ˜๋กœ๋ถ€ํ„ฐ ์ž๋™์œผ๋กœ ๋ณต๊ตฌ๋  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ์ฝœ๋ฐฑ. * **optional** `identifierPrefix` : React๊ฐ€ [`useId`](/reference/react/useId)์— ์˜ํ•ด ์ƒ์„ฑ๋œ ID์— ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ž์—ด ์ ‘๋‘์‚ฌ. ๊ฐ™์€ ํŽ˜์ด์ง€์—์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฃจํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ถฉ๋Œ์„ ํ”ผํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. +======= + * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`. + * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown, and an `errorInfo` object containing the `componentStack`. + * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. Called with an `error` React throws, and an `errorInfo` object containing the `componentStack`. Some recoverable errors may include the original error cause as `error.cause`. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 #### ๋ฐ˜ํ™˜๊ฐ’ {/*returns*/} @@ -344,12 +351,6 @@ export default function App({counter}) { ### Show a dialog for uncaught errors {/*show-a-dialog-for-uncaught-errors*/} - - -`onUncaughtError` is only available in the latest React Canary release. - - - By default, React will log all uncaught errors to the console. To implement your own error reporting, you can provide the optional `onUncaughtError` root option: ```js [[1, 6, "onUncaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack"]] @@ -576,28 +577,11 @@ export default function App() { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "^5.0.0" - }, - "main": "/index.js" -} -``` - ### Displaying Error Boundary errors {/*displaying-error-boundary-errors*/} - - -`onCaughtError` is only available in the latest React Canary release. - - - By default, React will log all errors caught by an Error Boundary to `console.error`. To override this behavior, you can provide the optional `onCaughtError` root option to handle errors caught by an [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary): ```js [[1, 6, "onCaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack"]] @@ -863,8 +847,8 @@ function Throw({error}) { ```json package.json hidden { "dependencies": { - "react": "canary", - "react-dom": "canary", + "react": "19.0.0-rc-3edc000d-20240926", + "react-dom": "19.0.0-rc-3edc000d-20240926", "react-scripts": "^5.0.0", "react-error-boundary": "4.0.3" }, @@ -1121,8 +1105,8 @@ function Throw({error}) { ```json package.json hidden { "dependencies": { - "react": "canary", - "react-dom": "canary", + "react": "19.0.0-rc-3edc000d-20240926", + "react-dom": "19.0.0-rc-3edc000d-20240926", "react-scripts": "^5.0.0", "react-error-boundary": "4.0.3" }, diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 569314e49..20deca6c9 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -41,8 +41,8 @@ React๋Š” `domNode` ๋‚ด๋ถ€์˜ HTML์— ๋ถ™์–ด, ๋‚ด๋ถ€ DOM์„ ์ง์ ‘ ๊ด€๋ฆฌํ•  ๊ฒƒ * **optional** `options`: React root์— ์˜ต์…˜์„ ์ฃผ๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. - * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`. - * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown and an `errorInfo` object containing the `componentStack`. + * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`. + * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown and an `errorInfo` object containing the `componentStack`. * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. Called with the `error` React throws, and an `errorInfo` object containing the `componentStack`. Some recoverable errors may include the original error cause as `error.cause`. * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as used on the server. @@ -375,6 +375,7 @@ hydrate๋œ root์—์„œ [`root.render`](#root-render)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์€ ํ” ### ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์—๋Ÿฌ์— ๋Œ€ํ•œ ๋Œ€ํ™” ์ƒ์ž ํ‘œ์‹œํ•˜๊ธฐ {/*show-a-dialog-for-uncaught-errors*/} +<<<<<<< HEAD `onUncaughtError`๋Š” ์ตœ์‹  React Canary ๋ฆด๋ฆฌ์Šค์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -382,6 +383,9 @@ hydrate๋œ root์—์„œ [`root.render`](#root-render)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์€ ํ” ๊ธฐ๋ณธ์ ์œผ๋กœ React๋Š” ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ๋ชจ๋“  ์—๋Ÿฌ๋ฅผ ์ฝ˜์†”์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ž์ฒด์ ์ธ ์—๋Ÿฌ ๋ณด๊ณ  ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์„ ํƒ์  root ์˜ต์…˜์ธ `onUncaughtError`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= +By default, React will log all uncaught errors to the console. To implement your own error reporting, you can provide the optional `onUncaughtError` root option: +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ```js [[1, 7, "onUncaughtError"], [2, 7, "error", 1], [3, 7, "errorInfo"], [4, 11, "componentStack"]] import { hydrateRoot } from 'react-dom/client'; @@ -609,22 +613,12 @@ export default function App() { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "^5.0.0" - }, - "main": "/index.js" -} -``` - ### Error Boundary ์—๋Ÿฌ ํ‘œ์‹œํ•˜๊ธฐ {/*displaying-error-boundary-errors*/} +<<<<<<< HEAD `onCaughtError`๋Š” ์ตœ์‹  React Canary ๋ฆด๋ฆฌ์Šค์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -632,6 +626,9 @@ export default function App() { ๊ธฐ๋ณธ์ ์œผ๋กœ React๋Š” Error Boundary์— ์˜ํ•ด ์žกํžŒ ๋ชจ๋“  ์—๋Ÿฌ๋ฅผ `console.error`์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ด ๋™์ž‘์„ ์žฌ์ •์˜ํ•˜๋ ค๋ฉด [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary)์—์„œ ์žกํžŒ ์—๋Ÿฌ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์„ ํƒ์  root ์˜ต์…˜์ธ `onCaughtError`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= +By default, React will log all errors caught by an Error Boundary to `console.error`. To override this behavior, you can provide the optional `onCaughtError` root option for errors caught by an [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary): +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ```js [[1, 7, "onCaughtError"], [2, 7, "error", 1], [3, 7, "errorInfo"], [4, 11, "componentStack"]] import { hydrateRoot } from 'react-dom/client'; @@ -898,8 +895,8 @@ function Throw({error}) { ```json package.json hidden { "dependencies": { - "react": "canary", - "react-dom": "canary", + "react": "19.0.0-rc-3edc000d-20240926", + "react-dom": "19.0.0-rc-3edc000d-20240926", "react-scripts": "^5.0.0", "react-error-boundary": "4.0.3" }, @@ -1158,8 +1155,8 @@ function Throw({error}) { ```json package.json hidden { "dependencies": { - "react": "canary", - "react-dom": "canary", + "react": "19.0.0-rc-3edc000d-20240926", + "react-dom": "19.0.0-rc-3edc000d-20240926", "react-scripts": "^5.0.0", "react-error-boundary": "4.0.3" }, diff --git a/src/content/reference/react-dom/components/common.md b/src/content/reference/react-dom/components/common.md index 70c67d990..4a11cedf8 100644 --- a/src/content/reference/react-dom/components/common.md +++ b/src/content/reference/react-dom/components/common.md @@ -248,6 +248,7 @@ capture-phase-events) [`useRef`](/reference/react/useRef#manipulating-the-dom-with-a-ref) ์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ref ๊ฐ์ฒด ๋Œ€์‹  `ref` ์†์„ฑ์— ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```js +<<<<<<< HEAD
console.log(node)} /> ``` @@ -269,22 +270,43 @@ React๋Š” *๋‹ค๋ฅธ* `ref` ์ฝœ๋ฐฑ์„ ์ „๋‹ฌํ•  ๋•Œ ๋งˆ๋‹ค `ref` ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•ฉ ```js +======= +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04
{ - console.log(node); + console.log('Attached', node); return () => { console.log('Clean up', node) } }}> - ``` +[See an example of using the `ref` callback.](/learn/manipulating-the-dom-with-refs#how-to-manage-a-list-of-refs-using-a-ref-callback) + +When the `
` DOM node is added to the screen, React will call your `ref` callback with the DOM `node` as the argument. When that `
` DOM node is removed, React will call your the cleanup function returned from the callback. + +React will also call your `ref` callback whenever you pass a *different* `ref` callback. In the above example, `(node) => { ... }` is a different function on every render. When your component re-renders, the *previous* function will be called with `null` as the argument, and the *next* function will be called with the DOM node. + +#### Parameters {/*ref-callback-parameters*/} + +* `node`: A DOM node. React will pass you the DOM node when the ref gets attached. Unless you pass the same function reference for the `ref` callback on every render, the callback will get temporarily cleanup and re-create during every re-render of the component. + + + +#### React 19 added cleanup functions for `ref` callbacks. {/*react-19-added-cleanup-functions-for-ref-callbacks*/} + +To support backwards compatibility, if a cleanup function is not returned from the `ref` callback, `node` will be called with `null` when the `ref` is detached. This behavior will be removed in a future version. + + + +#### Returns {/*returns*/} + +* **optional** `cleanup function`: When the `ref` is detached, React will call the cleanup function. If a function is not returned by the `ref` callback, React will call the callback again with `null` as the argument when the `ref` gets detached. This behavior will be removed in a future version. + #### Caveats {/*caveats*/} * When Strict Mode is on, React will **run one extra development-only setup+cleanup cycle** before the first real setup. This is a stress-test that ensures that your cleanup logic "mirrors" your setup logic and that it stops or undoes whatever the setup is doing. If this causes a problem, implement the cleanup function. -* When you pass a *different* `ref` callback, React will call the *previous* callback's cleanup function if provided. If not cleanup function is defined, the `ref` callback will be called with `null` as the argument. The *next* function will be called with the DOM node. - - +* When you pass a *different* `ref` callback, React will call the *previous* callback's cleanup function if provided. If no cleanup function is defined, the `ref` callback will be called with `null` as the argument. The *next* function will be called with the DOM node. --- diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index b4bc96b26..c28d9401b 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -1,8 +1,8 @@ --- title: "
" -canary: true --- +<<<<<<< HEAD React์˜ ์ต์Šคํ…์…˜์ธ ``์€ ํ˜„์žฌ React Canary(์นด๋‚˜๋ฆฌ)์™€ ์‹คํ—˜์  ์ฑ„๋„์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React์—์„œ์˜ ์•ˆ์ •์ ์ธ ๋ฐฐํฌ๋ฅผ ์œ„ํ•ด ``์€ [๋‚ด์žฅ ๋ธŒ๋ผ์šฐ์ € HTML ์ปดํฌ๋„ŒํŠธ](https://react.dev/reference/react-dom/components#all-html-components)๋กœ์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋” ์ž์„ธํ•œ ์‚ฌํ•ญ์€ [React ๋ฐฐํฌ ์ฑ„๋„](/community/versioning-policy#all-release-channels)์„ ํ™•์ธํ•˜์„ธ์š”. @@ -10,6 +10,8 @@ React์˜ ์ต์Šคํ…์…˜์ธ ``์€ ํ˜„์žฌ React Canary(์นด๋‚˜๋ฆฌ)์™€ ์‹คํ—˜์  +======= +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 [๋‚ด์žฅ ๋ธŒ๋ผ์šฐ์ € `` ์ปดํฌ๋„ŒํŠธ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)๋Š” ์ •๋ณด ์ œ์ถœ์„ ์œ„ํ•œ ๋Œ€ํ™”ํ˜• ์ปจํŠธ๋กค์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -78,20 +80,9 @@ export default function Search() { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "18.3.0-canary-6db7f4209-20231021", - "react-dom": "18.3.0-canary-6db7f4209-20231021", - "react-scripts": "^5.0.0" - }, - "main": "/index.js", - "devDependencies": {} -} -``` - +<<<<<<< HEAD ### Server Action์—์„œ ํผ ์ œ์ถœ ์ฒ˜๋ฆฌํ•˜๊ธฐ {/*handle-form-submission-with-a-server-action*/} ์ž…๋ ฅ๊ณผ ์ œ์ถœ ๋ฒ„ํŠผ๊ณผ ํ•จ๊ป˜ ``์„ ๋ Œ๋”๋งํ•˜์„ธ์š”. ํผ์ด ์ œ์ถœ๋  ๋•Œ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด Server Action([`'use server'`](/reference/rsc/use-server)๊ฐ€ ํ‘œ์‹œ๋œ ํ•จ์ˆ˜)๋ฅผ ํผ์˜ `action`์˜ ํ”„๋กœํผํ‹ฐ๋กœ ์ „๋‹ฌํ•˜์„ธ์š”. @@ -100,6 +91,15 @@ export default function Search() { ``์˜ ์•ก์…˜์— ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ํผ ํ•„๋“œ์˜ `hidden`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Server Action์€ [`formData`](https://developer.mozilla.org/ko/docs/Web/API/FormData) ๋Œ€์‹  `hidden`์ด ์ ์šฉ๋œ ํผ ํ•„๋“œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= +### Handle form submission with a Server Function {/*handle-form-submission-with-a-server-function*/} + +Render a `` with an input and submit button. Pass a Server Function (a function marked with [`'use server'`](/reference/rsc/use-server)) to the `action` prop of form to run the function when the form is submitted. + +Passing a Server Function to `` allow users to submit forms without JavaScript enabled or before the code has loaded. This is beneficial to users who have a slow connection, device, or have JavaScript disabled and is similar to the way forms work when a URL is passed to the `action` prop. + +You can use hidden form fields to provide data to the ``'s action. The Server Function will be called with the hidden form field data as an instance of [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData). +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ```jsx import { updateCart } from './lib.js'; @@ -139,7 +139,11 @@ function AddToCart({productId}) { } ``` +<<<<<<< HEAD ``์ด [์„œ๋ฒ„์ปดํฌ๋„ŒํŠธ](/reference/rsc/use-client)์— ์˜ํ•ด ๋ Œ๋”๋ง๋˜๊ณ  [Server Action](/reference/rsc/use-server)์ด ``์˜ `action` ํ”„๋กœํผํ‹ฐ์— ์ „๋‹ฌ ๋˜๋ฉด, ํผ์€ [์ ์ง„์ ์œผ๋กœ ํ–ฅ์ƒ](https://developer.mozilla.org/ko/docs/Glossary/Progressive_Enhancement)๋ฉ๋‹ˆ๋‹ค. +======= +When `` is rendered by a [Server Component](/reference/rsc/use-client), and a [Server Function](/reference/rsc/server-function) is passed to the ``'s `action` prop, the form is [progressively enhanced](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 ### ํผ์ด ์ œ์ถœ๋˜๋Š” ๋™์•ˆ pending ์ƒํƒœ ๋ณด์—ฌ์ฃผ๊ธฐ {/*display-a-pending-state-during-form-submission*/} @@ -181,17 +185,6 @@ export async function submitForm(query) { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "^5.0.0" - }, - "main": "/index.js", - "devDependencies": {} -} -``` `useFormStatus` hook์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด, [์ฐธ๊ณ  ๋ฌธ์„œ](/reference/react-dom/hooks/useFormStatus)๋ฅผ ํ™•์ธํ•˜์„ธ์š”. @@ -263,19 +256,6 @@ export async function deliverMessage(message) { } ``` - -```json package.json hidden -{ - "dependencies": { - "react": "18.3.0-canary-6db7f4209-20231021", - "react-dom": "18.3.0-canary-6db7f4209-20231021", - "react-scripts": "^5.0.0" - }, - "main": "/index.js", - "devDependencies": {} -} -``` - `useOptimistic` hook์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด [์ฐธ๊ณ  ๋ฌธ์„œ](/reference/react/hooks/useOptimistic)๋ฅผ ํ™•์ธํ•ด ๋ณด์„ธ์š”. @@ -310,8 +290,8 @@ export default function Search() { ```json package.json hidden { "dependencies": { - "react": "18.3.0-canary-6db7f4209-20231021", - "react-dom": "18.3.0-canary-6db7f4209-20231021", + "react": "19.0.0-rc-3edc000d-20240926", + "react-dom": "19.0.0-rc-3edc000d-20240926", "react-scripts": "^5.0.0", "react-error-boundary": "4.0.3" }, @@ -326,11 +306,19 @@ export default function Search() { ์ ์ง„์  ํ–ฅ์ƒ์„ ์œ„ํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฒˆ๋“ค์ด ๋กœ๋“œ๋˜๊ธฐ ์ „ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ์š”์†Œ๋“ค์ด ์ง€์ผœ์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. +<<<<<<< HEAD 1. ``์ด [์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ](/reference/rsc/use-client)์—์„œ ๋ Œ๋”. 2. ``์˜ `action` ํ”„๋กœํผํ‹ฐ๋กœ ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๊ฐ€ [Server Action](/reference/rsc/use-server). 3. `useActionState` hook์ด ์—๋Ÿฌ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ. `useActionState`๋Š” [Server Action](/reference/rsc/use-server)๊ณผ ์ดˆ๊ธฐ ์ƒํƒœ ๊ฐ’์ด๋ผ๋Š” ๋‘ ๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. `useActionState`๋Š” ์ƒํƒœ ๋ณ€์ˆ˜์™€ ์•ก์…˜์ด๋ผ๋Š” ๋‘ ๊ฐœ์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. `useActionState`๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜๋œ ์•ก์…˜์€ ํผ์˜ `action` ํ”„๋กœํผํ‹ฐ์— ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. `useActionState`๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜๋œ ์ƒํƒœ ๋ณ€์ˆ˜๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. `useActionState`์— ์ „๋‹ฌ๋œ [Server Action](/reference/rsc/use-server)์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ’์€ ์ƒํƒœ ๋ณ€์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. +======= +1. `` be rendered by a [Server Component](/reference/rsc/use-client) +1. the function passed to the ``'s `action` prop be a [Server Function](/reference/rsc/server-functions) +1. the `useActionState` Hook be used to display the error message + +`useActionState` takes two parameters: a [Server Function](/reference/rsc/server-functions) and an initial state. `useActionState` returns two values, a state variable and an action. The action returned by `useActionState` should be passed to the `action` prop of the form. The state variable returned by `useActionState` can be used to display an error message. The value returned by the Server Function passed to `useActionState` will be used to update the state variable. +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 @@ -376,18 +364,6 @@ export async function signUpNewUser(newEmail) { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "^5.0.0" - }, - "main": "/index.js", - "devDependencies": {} -} -``` - [`useActionState`](/reference/react/useActionState)๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ํผ ์ž‘์—…์—์„œ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์„ธ์š”. @@ -424,16 +400,4 @@ export default function Search() { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "18.3.0-canary-6db7f4209-20231021", - "react-dom": "18.3.0-canary-6db7f4209-20231021", - "react-scripts": "^5.0.0" - }, - "main": "/index.js", - "devDependencies": {} -} -``` - diff --git a/src/content/reference/react-dom/components/input.md b/src/content/reference/react-dom/components/input.md index 2fd3bba0d..584cc9611 100644 --- a/src/content/reference/react-dom/components/input.md +++ b/src/content/reference/react-dom/components/input.md @@ -32,13 +32,7 @@ input ์„ ํ‘œ์‹œํ•˜๋ ค๋ฉด, [`` ๋ธŒ๋ผ์šฐ์ € ๋‚ด์žฅ ์ปดํฌ๋„ŒํŠธ](https:// `` ์€ [์ผ๋ฐ˜์ ์ธ ์—˜๋ฆฌ๋จผํŠธ props](/reference/react-dom/components/common#props) ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. - - -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](/reference/react-dom/components#all-html-components). Learn more about [React's release channels here](/community/versioning-policy#all-release-channels). - - - -[`formAction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formaction): A string or function. Overrides the parent `` 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 [``](/reference/react-dom/components/form#props). +- [`formAction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formaction): A string or function. Overrides the parent `` 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 [``](/reference/react-dom/components/form#props). You can [make an input controlled](#controlling-an-input-with-a-state-variable) by passing one of these props: diff --git a/src/content/reference/react-dom/components/link.md b/src/content/reference/react-dom/components/link.md index 29f1968aa..37aa697b2 100644 --- a/src/content/reference/react-dom/components/link.md +++ b/src/content/reference/react-dom/components/link.md @@ -1,14 +1,16 @@ --- link: "" -canary: true --- +<<<<<<< HEAD React์˜ `` ํ™•์žฅ์€ ํ˜„์žฌ React์˜ ์นด๋‚˜๋ฆฌ(Canary) ์ฑ„๋„๊ณผ ์‹คํ—˜ ์ฑ„๋„์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React์˜ ์•ˆ์ •์ ์ธ ๋ฆด๋ฆฌ์ฆˆ์—์„œ๋Š” ``๊ฐ€ [๋‚ด์žฅ ๋ธŒ๋ผ์šฐ์ € HTML ์ปดํฌ๋„ŒํŠธ](https://react.dev/reference/react-dom/components#all-html-components)๋กœ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ [React ๋ฆด๋ฆฌ์ฆˆ ์ฑ„๋„](/community/versioning-policy#all-release-channels)์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +======= +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 [๋ธŒ๋ผ์šฐ์ € ๋‚ด์žฅ `` ์ปดํฌ๋„ŒํŠธ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)๋Š” ์Šคํƒ€์ผ์‹œํŠธ์™€ ๊ฐ™์€ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋งํฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋กœ ๋ฌธ์„œ๋ฅผ ์ฃผ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. diff --git a/src/content/reference/react-dom/components/meta.md b/src/content/reference/react-dom/components/meta.md index d60d971fa..cadec241c 100644 --- a/src/content/reference/react-dom/components/meta.md +++ b/src/content/reference/react-dom/components/meta.md @@ -1,8 +1,8 @@ --- meta: "" -canary: true --- +<<<<<<< HEAD React์˜ `` ํ™•์žฅ์€ ํ˜„์žฌ React์˜ ์นด๋‚˜๋ฆฌ(Canary) ๋ฒ„์ „ ๋ฐ ์‹คํ—˜ ์ฑ„๋„์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React์˜ ์•ˆ์ •์ ์ธ ๋ฆด๋ฆฌ์ฆˆ์—์„œ๋Š” ``๊ฐ€ [๋‚ด์žฅ ๋ธŒ๋ผ์šฐ์ € HTML ์ปดํฌ๋„ŒํŠธ](/reference/react-dom/components#all-html-components)๋กœ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ [React์˜ ๋ฆด๋ฆฌ์ฆˆ ์ฑ„๋„](/community/versioning-policy#all-release-channels)์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์‹ญ์‹œ์˜ค. @@ -10,6 +10,8 @@ React์˜ `` ํ™•์žฅ์€ ํ˜„์žฌ React์˜ ์นด๋‚˜๋ฆฌ(Canary) ๋ฒ„์ „ ๋ฐ ์‹คํ—˜ +======= +>>>>>>> 3b02f828ff2a4f9d2846f077e442b8a405e2eb04 [๋‚ด์žฅ ๋ธŒ๋ผ์šฐ์ € `` ์ปดํฌ๋„ŒํŠธ](https://developer.mozilla.org/ko/docs/Web/HTML/Element/meta)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์„œ์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/src/content/reference/react-dom/components/script.md b/src/content/reference/react-dom/components/script.md index 037155b2c..7b31da221 100644 --- a/src/content/reference/react-dom/components/script.md +++ b/src/content/reference/react-dom/components/script.md @@ -1,14 +1,16 @@ --- script: " +``` + +On the client, your bootstrap script should [hydrate the entire `document` with a call to `hydrateRoot`:](/reference/react-dom/client/hydrateRoot#hydrating-an-entire-document) + +```js [[1, 4, ""]] +import { hydrateRoot } from 'react-dom/client'; +import App from './App.js'; + +hydrateRoot(document, ); +``` + +This will attach event listeners to the static server-generated HTML and make it interactive. + + + +#### Reading CSS and JS asset paths from the build output {/*reading-css-and-js-asset-paths-from-the-build-output*/} + +The final asset URLs (like JavaScript and CSS files) are often hashed after the build. For example, instead of `styles.css` you might end up with `styles.123456.css`. Hashing static asset filenames guarantees that every distinct build of the same asset will have a different filename. This is useful because it lets you safely enable long-term caching for static assets: a file with a certain name would never change content. + +However, if you don't know the asset URLs until after the build, there's no way for you to put them in the source code. For example, hardcoding `"/styles.css"` into JSX like earlier wouldn't work. To keep them out of your source code, your root component can read the real filenames from a map passed as a prop: + +```js {1,6} +export default function App({ assetMap }) { + return ( + + + My app + + + ... + + ); +} +``` + +On the server, render `` and pass your `assetMap` with the asset URLs: + +```js {1-5,8,9} +// You'd need to get this JSON from your build tooling, e.g. read it from the build output. +const assetMap = { + 'styles.css': '/styles.123456.css', + 'main.js': '/main.123456.js' +}; + +async function handler(request) { + const {prelude} = await prerender(, { + bootstrapScripts: [assetMap['/main.js']] + }); + return new Response(prelude, { + headers: { 'content-type': 'text/html' }, + }); +} +``` + +Since your server is now rendering ``, you need to render it with `assetMap` on the client too to avoid hydration errors. You can serialize and pass `assetMap` to the client like this: + +```js {9-10} +// You'd need to get this JSON from your build tooling. +const assetMap = { + 'styles.css': '/styles.123456.css', + 'main.js': '/main.123456.js' +}; + +async function handler(request) { + const {prelude} = await prerender(, { + // Careful: It's safe to stringify() this because this data isn't user-generated. + bootstrapScriptContent: `window.assetMap = ${JSON.stringify(assetMap)};`, + bootstrapScripts: [assetMap['/main.js']], + }); + return new Response(prelude, { + headers: { 'content-type': 'text/html' }, + }); +} +``` + +In the example above, the `bootstrapScriptContent` option adds an extra inline ` +``` + +On the client, your bootstrap script should [hydrate the entire `document` with a call to `hydrateRoot`:](/reference/react-dom/client/hydrateRoot#hydrating-an-entire-document) + +```js [[1, 4, ""]] +import { hydrateRoot } from 'react-dom/client'; +import App from './App.js'; + +hydrateRoot(document, ); +``` + +This will attach event listeners to the static server-generated HTML and make it interactive. + + + +#### Reading CSS and JS asset paths from the build output {/*reading-css-and-js-asset-paths-from-the-build-output*/} + +The final asset URLs (like JavaScript and CSS files) are often hashed after the build. For example, instead of `styles.css` you might end up with `styles.123456.css`. Hashing static asset filenames guarantees that every distinct build of the same asset will have a different filename. This is useful because it lets you safely enable long-term caching for static assets: a file with a certain name would never change content. + +However, if you don't know the asset URLs until after the build, there's no way for you to put them in the source code. For example, hardcoding `"/styles.css"` into JSX like earlier wouldn't work. To keep them out of your source code, your root component can read the real filenames from a map passed as a prop: + +```js {1,6} +export default function App({ assetMap }) { + return ( + + + My app + + + ... + + ); +} +``` + +On the server, render `` and pass your `assetMap` with the asset URLs: + +```js {1-5,8,9} +// You'd need to get this JSON from your build tooling, e.g. read it from the build output. +const assetMap = { + 'styles.css': '/styles.123456.css', + 'main.js': '/main.123456.js' +}; + +app.use('/', async (request, response) => { + const { prelude } = await prerenderToNodeStream(, { + bootstrapScripts: [assetMap['/main.js']] + }); + + response.setHeader('Content-Type', 'text/html'); + prelude.pipe(response); +}); +``` + +Since your server is now rendering ``, you need to render it with `assetMap` on the client too to avoid hydration errors. You can serialize and pass `assetMap` to the client like this: + +```js {9-10} +// You'd need to get this JSON from your build tooling. +const assetMap = { + 'styles.css': '/styles.123456.css', + 'main.js': '/main.123456.js' +}; + +app.use('/', async (request, response) => { + const { prelude } = await prerenderToNodeStream(, { + // Careful: It's safe to stringify() this because this data isn't user-generated. + bootstrapScriptContent: `window.assetMap = ${JSON.stringify(assetMap)};`, + bootstrapScripts: [assetMap['/main.js']], + }); + + response.setHeader('Content-Type', 'text/html'); + prelude.pipe(response); +}); +``` + +In the example above, the `bootstrapScriptContent` option adds an extra inline `