diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 2a905a0df..b1ef428d0 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 @@ -41,7 +49,7 @@ jobs: run: npx -p nextjs-bundle-analysis@0.5.0 report - name: Upload bundle - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: .next/analyze/__bundle_analysis.json name: bundle_analysis.json @@ -73,7 +81,7 @@ jobs: run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare - name: Upload analysis comment - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: analysis_comment.txt path: .next/analyze/__bundle_analysis_comment.txt @@ -82,7 +90,7 @@ jobs: run: echo ${{ github.event.number }} > ./pr_number - name: Upload PR number - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pr_number path: ./pr_number diff --git a/.github/workflows/site_lint.yml b/.github/workflows/site_lint.yml index 107b36cb7..7f4268a6c 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/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 4e19039ed..9cdf256fb 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() { @@ -370,6 +371,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 69b207a9d..76d334191 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 898066454..d00b9b33e 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 && (
+ +これまでは、コンポーネントがサスペンドされた場合、サスペンド対象の兄弟コンポーネントがレンダーされてからフォールバックがコミットされていた。 + + + + + +React 19 では、コンポーネントがサスペンドすると、フォールバックがコミットされた後で、サスペンド対象の兄弟コンポーネントがレンダーされる。 + + + +この変更により、サスペンスのフォールバックがより早く表示される一方で、サスペンドされたツリー内にある遅延リクエストも事前に準備されるようになります。 + ### UMD ビルドの削除 {/*umd-builds-removed*/} UMD は過去には、ビルドステップなしで React を読み込むための便利な方法として広く使用されていました。現在では、HTML ドキュメント内でスクリプトとしてモジュールをロードするためのモダンな代替手段があります。テストとリリースプロセスの複雑性を軽減するため、React 19 からは UMD ビルドを生成しなくなります。 @@ -717,12 +730,12 @@ const reducer = (state: State, action: Action) => state; ### その他の破壊的変更 {/*other-breaking-changes*/} -- **react-dom**: src/href での JavaScript URL に対するエラー [#26507](https://github.com/facebook/react/pull/26507) +- **react-dom**: `src` と `href での JavaScript URL に対するエラー [#26507](https://github.com/facebook/react/pull/26507) - **react-dom**: `onRecoverableError` から `errorInfo.digest` を削除 [#28222](https://github.com/facebook/react/pull/28222) - **react-dom**: `unstable_flushControlled` を削除 [#26397](https://github.com/facebook/react/pull/26397) - **react-dom**: `unstable_createEventHandle` を削除 [#28271](https://github.com/facebook/react/pull/28271) - **react-dom**: `unstable_renderSubtreeIntoContainer` を削除 [#28271](https://github.com/facebook/react/pull/28271) -- **react-dom**: `unstable_runWithPrioirty` を削除 [#28271](https://github.com/facebook/react/pull/28271) +- **react-dom**: `unstable_runWithPriority` を削除 [#28271](https://github.com/facebook/react/pull/28271) - **react-is**: `react-is` から非推奨のメソッドを削除 [28224](https://github.com/facebook/react/pull/28224) ### その他の注目すべき変更点 {/*other-notable-changes*/} @@ -734,7 +747,7 @@ const reducer = (state: State, action: Action) => state; - **react-dom**: SSR 中のレイアウトエフェクト警告を削除 [#26395](https://github.com/facebook/react/pull/26395) - **react-dom**: src/href に空文字列を設定しないよう警告(アンカータグを除く)[#28124](https://github.com/facebook/react/pull/28124) -React 19 の安定版リリース時に、完全な変更履歴を公開します。 +全変更点のリストについては、[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 4f566ffcc..edbac1810 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 @@ May 22, 2024 by [Ricky Hanlon](https://twitter.com/rickhanlonii). --- -React Conf 2024 では、[React 19 RC](/blog/2024/04/25/react-19)、[React Native New Architecture Beta](https://github.com/reactwg/react-native-new-architecture/discussions/189)、および [React Compiler](/learn/react-compiler) の実験的リリースを発表しました。コミュニティもステージに立ち、[React Router v7](https://remix.run/blog/merging-remix-and-react-router)、Expo Router の [Universal Server Components](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=20765s)、[RedwoodJS](https://redwoodjs.com/blog/rsc-now-in-redwoodjs) での React Server Components など、多くの発表を行いました。 +React Conf 2024 では、[React 19 RC](/blog/2024/12/05/react-19)、[React Native New Architecture Beta](https://github.com/reactwg/react-native-new-architecture/discussions/189)、および [React Compiler](/learn/react-compiler) の実験的リリースを発表しました。コミュニティもステージに立ち、[React Router v7](https://remix.run/blog/merging-remix-and-react-router)、Expo Router の [Universal Server Components](https://www.youtube.com/watch?v=T8TZQ6k4SLE&t=20765s)、[RedwoodJS](https://redwoodjs.com/blog/rsc-now-in-redwoodjs) での React Server Components など、多くの発表を行いました。 [1 日目](https://www.youtube.com/watch?v=T8TZQ6k4SLE) と [2 日目](https://www.youtube.com/watch?v=0ckOUBiuxVY)の全ストリームがオンラインで視聴可能です。この投稿では、イベントでの講演と発表をまとめます。 @@ -36,7 +36,7 @@ _[1 日目の全ストリームはこちらから視聴できます。](https:// - [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) -次の基調講演では、[Josh Story](https://twitter.com/joshcstory) と [Andrew Clark](https://twitter.com/acdlite) が React 19 に登場する新機能を共有し、React 19 RC が本番環境でのテストに準備が整ったことを発表しました。すべての機能については [React 19 リリースポスト](/blog/2024/04/25/react-19)をご覧ください。また、新機能について詳しく知りたい方は以下の講演をご覧ください。 +次の基調講演では、[Josh Story](https://twitter.com/joshcstory) と [Andrew Clark](https://twitter.com/acdlite) が React 19 に登場する新機能を共有し、React 19 RC が本番環境でのテストに準備が整ったことを発表しました。すべての機能については [React 19 リリースポスト](/blog/2024/12/05/react-19)をご覧ください。また、新機能について詳しく知りたい方は以下の講演をご覧ください。 - [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/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 24c3f5c3f..5ba830c3d 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 が npm で利用可能になりました! この投稿では React 19 の新機能、およびそれらをどのように採用するかについて概説します。 +date: 2024/12/05 +description: React 19 が npm で利用可能になりました! この投稿では React 19 の新機能、およびそれらをどのように採用するかについて概説します。 --- -April 25, 2024 by [The React Team](/community/team) +December 05, 2024 by [The React Team](/community/team) --- + + +### React 19 は安定版になりました {/*react-19-is-now-stable*/} + +4 月に React 19 RC の記事として本記事が公開されて以降に、以下の内容が追加となっています。 + +- **サスペンド中のツリーのプリウォーム**:[サスペンスに関する改善](/blog/2024/04/25/react-19-upgrade-guide#improvements-to-suspense) +- **静的サイト用の React DOM API**: [静的サイト用の新 DOM API](#new-react-dom-static-apis) + +_この記事の投稿日時も、安定版リリースに合わせて変更となっています。_ + + -npm で React 19 Beta が利用可能になりました! +npm で React 19 が利用可能になりました! -[React 19 RC アップグレードガイド](/blog/2024/04/25/react-19-upgrade-guide)では、アプリを React 19 にアップグレードするためのステップバイステップガイドをお示ししました。この投稿では、React 19 の新機能と、それらをどのように採用するかについて概説します。 +[React 19 アップグレードガイド](/blog/2024/04/25/react-19-upgrade-guide)では、アプリを React 19 にアップグレードするためのステップバイステップガイドをお示ししました。この投稿では、React 19 の新機能と、それらをどのように採用するかについて概説します。 - [React 19 の新機能](#whats-new-in-react-19) - [React 19 の改善点](#improvements-in-react-19) @@ -312,6 +324,30 @@ function Heading({children}) { 詳細については、[`use`](/reference/react/use) のドキュメントをご覧ください。 +## 静的サイト用の新 DOM API {/*new-react-dom-static-apis*/} + +静的サイト生成 (static site generation) のための API を `react-dom/static` に 2 つ追加しました。 +- [`prerender`](/reference/react-dom/static/prerender) +- [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream) + +これらは `renderToString` の改善版であり、静的な HTML 生成の際に、データの待機を行うようになっています。Node.js のストリームや Web 標準のストリームで動作するよう設計されています。例えば Web ストリームの環境では、`prerender` を使って React ツリーを静的な HTML にプリレンダーできます。 + +```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' }, + }); +} +``` + +プリレンダー API は、静的な HTML をストリームとして返す前に、すべてのデータの読み込みを待機します。このストリームは文字列に変換することも、レスポンスに含めて送信することも可能です。ただし、既存の [React DOM サーバレンダリング API](/reference/react-dom/server) がサポートするような、データを読み込みながらコンテンツをストリーミングする機能はサポートしていません。 + +詳細については [React DOM 静的サイト用 API](/reference/react-dom/static) を参照してください。 ## React Server Components {/*react-server-components*/} @@ -771,5 +807,4 @@ React におけるカスタム要素のサポートに関し、設計と実装 #### アップグレード方法 {/*how-to-upgrade*/} アップグレードに関するステップバイステップのガイドや、重要な変更点の完全なリストについては、[React 19 アップグレードガイド](/blog/2024/04/25/react-19-upgrade-guide)を参照してください。 - - +_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 f4b1523da..87b67b1e0 100644 --- a/src/content/blog/index.md +++ b/src/content/blog/index.md @@ -14,25 +14,25 @@ React チームからの公式な更新のお知らせはこのブログに掲
- + -以前 React Conf 2024 で React Compiler の実験的リリースを行いました。それ以降も多くの進展がありましたので、この投稿では React Compiler の次の展開についてお伝えしたいと思います。 +React 19 アップグレードガイドでは、アプリを React 19 にアップグレードするためのステップバイステップガイドをお示ししました。この投稿では、React 19 の新機能と、それらをどのように採用するかについて概説します。 - + -先週、ネバダ州ヘンダーソンで 700 人以上の参加者が集まり、最新の UI エンジニアリングについて議論する 2 日間のカンファレンス、React Conf 2024 を開催しました。対面でのカンファレンスは 2019 年以来であり、コミュニティが再び一堂に会することができたことを大変に嬉しく思いました。 +以前 React Conf 2024 で React Compiler の実験的リリースを行いました。それ以降も多くの進展がありましたので、この投稿では React Compiler の次の展開についてお伝えしたいと思います。 - + -React 19 RC アップグレードガイドでは、アプリを React 19 にアップグレードするためのステップバイステップガイドをお示ししました。この投稿では、React 19 の新機能と、それらをどのように採用するかについて概説します。 +先週、ネバダ州ヘンダーソンで 700 人以上の参加者が集まり、最新の UI エンジニアリングについて議論する 2 日間のカンファレンス、React Conf 2024 を開催しました。対面でのカンファレンスは 2019 年以来であり、コミュニティが再び一堂に会することができたことを大変に嬉しく思いました。 - + React 19 に追加された改善にはいくつかの破壊的変更が必要ですが、アップグレードをできるだけスムーズに行えるよう努力しているため、ほとんどのアプリには影響が出ないことを予想しています。この投稿では、ライブラリを React 19 Beta にアップグレードする手順をご案内します。 diff --git a/src/content/community/acknowledgements.md b/src/content/community/acknowledgements.md index 02994c78c..575223321 100644 --- a/src/content/community/acknowledgements.md +++ b/src/content/community/acknowledgements.md @@ -4,7 +4,7 @@ title: 謝辞 -オリジナルの React は [Jordan Walke](https://github.com/jordwalke) によって作成されました。現在、React に取り組んでいる[フルタイムの専門チーム](/community/team)があり、また [1000 名を超えるオープンソース貢献者](https://github.com/facebook/react/blob/main/AUTHORS)がいます。 +オリジナルの React は [Jordan Walke](https://github.com/jordwalke) によって作成されました。現在、React に取り組んでいる[フルタイムの専門チーム](/community/team)があり、また [1000 名を超えるオープンソース貢献者](https://github.com/facebook/react/graphs/contributors)がいます。 diff --git a/src/content/community/team.md b/src/content/community/team.md index b627dbb56..136f0726c 100644 --- a/src/content/community/team.md +++ b/src/content/community/team.md @@ -18,7 +18,7 @@ React コアチームのメンバーは、コアコンポーネントの API、R Andrew は WordPress を使ったサイト作りからウェブ開発を始め、いつの間にか JavaScript にハマっていました。お気に入りの暇つぶしはカラオケです。日によってある時はディズニーの悪役に、またある時はディズニーのお姫様になっています。 - + Dan は Microsoft PowerPoint の中に偶然 Visual Basic を発見したことからプログラミングを始めました。[Sebastian](#sebastian-markbåge) のツイートを長文のブログ投稿に翻訳することが真の使命であると感じています。Fortnite では、ゲームが終わるまで茂みの中に隠れて勝利することがあります。 @@ -38,11 +38,11 @@ React コアチームのメンバーは、コアコンポーネントの API、R Joe は数学と哲学を専攻する予定でしたが、Matlab で物理シミュレーションを書いたことからコンピュータサイエンスに興味を持ちました。React に取り組む前は、Relay、RSocket.js、Skip プログラミング言語などに取り組んでいました。何かしらのリアクティブシステムを構築する傍らでは、ランニングをしたり、日本語を勉強したり、家族と過ごしたりしています。 - + Josh は大学で数学を専攻し、そこでプログラミングに出会いました。プロ開発者としての最初の仕事は、リアクティブプログラミングのお手本たる Microsoft Excel で保険料計算プログラムを書くことであり、きっとそれが今 React に取り組んでいる理由なのでしょう。その間 Josh はいくつかのスタートアップで IC、マネージャー、エグゼクティブも務めてきました。仕事以外では、料理で自分の限界に挑戦することが好きです。 - + Lauren のプログラミングキャリアは `` タグを初めて見たときにピークを迎えました。それ以来、彼女はその時の高揚感を追い続けています。大学ではコンピュータサイエンスではなく経済学を学んでいたため、コーディングは Java ではなく Excel で学びました。Lauren はチャットでお茶目なミームを投下したり、パートナとゲームを楽しんだり、犬の Zelda を可愛がったりするのが好きです。 @@ -62,7 +62,7 @@ React コアチームのメンバーは、コアコンポーネントの API、R Noah の UI プログラミングに対する興味に火が付いたのはニューヨーク大で音楽技術を学んでいる時でした。Meta では内部ツール、ブラウザ、ウェブパフォーマンスに関する業務を行い、現在は React に注力しています。仕事以外では、シンセサイザーをいじったり、猫と過ごしたりしています。 - + Ricky は理論数学を専攻していましたが、どういうわけか React Native チームで数年過ごしたあと、React チームにやってきました。プログラミングをしていないときは、スノーボード、自転車、クライミング、ゴルフを楽しんだり、テンプレートに合致しない GitHub の issue をクローズしたりしています。 diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index 456912ce5..66aece1a8 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,42 +309,10 @@ li { } ``` -```json package.json hidden -{ - "dependencies": { - "react": "canary", - "react-dom": "canary", - "react-scripts": "^5.0.0" - } -} -``` - この例では、`itemsRef` は単一の DOM ノードを保持していません。代わりに、アイテム ID から 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 を更新します。 -```js -
  • { - const map = getMap(); - if (node) { - // Add to the Map - map.set(cat, node); - } else { - // Remove from the Map - map.delete(cat); - } - }} -> -``` - -これにより、後で Map から個々の DOM ノードを読み取ることができます。 - - - -This example shows another approach for managing the Map with a `ref` callback cleanup function. - ```js
  • ``` - +こうしておけば、後で Map から個々の DOM ノードを読み取れるようになります。 + + + +Strict Mode が有効の場合、ref コールバックは開発環境で 2 回呼び出されます。 + +コールバック ref で[これがバグの発見にどう役立つのか](/reference/react/StrictMode#fixing-bugs-found-by-re-running-ref-callbacks-in-development)ご覧ください。 + + diff --git a/src/content/learn/react-compiler.md b/src/content/learn/react-compiler.md index 87bc2b76f..fbe0b0602 100644 --- a/src/content/learn/react-compiler.md +++ b/src/content/learn/react-compiler.md @@ -278,7 +278,7 @@ export default defineConfig(() => { ### Next.js {/*usage-with-nextjs*/} -詳細については [Next.js ドキュメント](https://nextjs.org/docs/canary/app/api-reference/next-config-js/reactCompiler)を参照してください。 +詳細については [Next.js ドキュメント](https://nextjs.org/docs/app/api-reference/next-config-js/reactCompiler)を参照してください。 ### Remix {/*usage-with-remix*/} `vite-plugin-babel` をインストールし、コンパイラ付属の Babel プラグインを追加します。 @@ -315,7 +315,7 @@ export default defineConfig({ ### Expo {/*usage-with-expo*/} -Expo アプリで React Compiler を有効化する方法については [Expo のドキュメント](https://docs.expo.dev/preview/react-compiler/)を参照してください。 +Expo アプリで React Compiler を有効化する方法については [Expo のドキュメント](https://docs.expo.dev/guides/react-compiler/)を参照してください。 ### Metro (React Native) {/*usage-with-react-native-metro*/} diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index 8a6e3fd0f..e6f2c0774 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -45,8 +45,8 @@ React で完全に構築されたアプリには、ルートコンポーネン * **省略可能** `options`: この React ルートに関するオプションが含まれたオブジェクト。 - * **省略可能** `onCaughtError`: エラーバウンダリ内で React がエラーをキャッチしたときに呼び出されるコールバック。エラーバウンダリにキャッチされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 - * **省略可能** `onUncaughtError`: エラーがスローされがエラーバウンダリでキャッチされななかったときに呼び出されるコールバック。スローされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 + * **省略可能** `onCaughtError`: エラーバウンダリ内で React がエラーをキャッチしたときに呼び出されるコールバック。エラーバウンダリにキャッチされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 + * **省略可能** `onUncaughtError`: エラーがスローされたがエラーバウンダリでキャッチされなかったときに呼び出されるコールバック。スローされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 * **省略可能** `onRecoverableError`: React が自動的にエラーから回復したときに呼び出されるコールバック。React がスローする `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。復帰可能なエラーの一部は元のエラーを `error.cause` として含んでいます。 * **省略可能** `identifierPrefix`: React が [`useId`](/reference/react/useId) によって生成する ID に使用する文字列プレフィックス。同じページ上に複数のルートを使用する際に、競合を避けるために用います。 @@ -346,12 +346,6 @@ export default function App({counter}) { ### キャッチされないエラーに対するダイアログを表示 {/*show-a-dialog-for-uncaught-errors*/} - - -`onUncaughtError` は最新版の React Canary リリースでのみ利用可能です。 - - - デフォルトでは React は、キャッチされなかったエラーをコンソールにログとして表示します。独自のエラーレポーティングを実装するには、省略可能なルートオプションである `onUncaughtError` を指定します。 ```js [[1, 6, "onUncaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack"]] @@ -578,28 +572,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*/} - - -`onCaughtError` は最新の React Canary リリースでのみ利用可能です。 - - - デフォルトでは、React はエラーバウンダリによってキャッチされたすべてのエラーを `console.error` に記録します。この動作をオーバーライドするには、省略可能なルートオプションである `onCaughtError` を指定して、[エラーバウンダリ](/reference/react/Component#catching-rendering-errors-with-an-error-boundary)によってキャッチされたエラーを処理するようにします。 ```js [[1, 6, "onCaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack"]] @@ -865,8 +842,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" }, @@ -1123,8 +1100,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 7c363a139..aa126b296 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 にアタッチし、その内部 * **省略可能** `options`: この React ルートのオプションを含むオブジェクト。 - * **省略可能** `onCaughtError`: エラーバウンダリ内で React がエラーをキャッチしたときに呼び出されるコールバック。エラーバウンダリにキャッチされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 - * **省略可能** `onUncaughtError`: エラーがスローされがエラーバウンダリでキャッチされななかったときに呼び出されるコールバック。スローされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 + * **省略可能** `onCaughtError`: エラーバウンダリ内で React がエラーをキャッチしたときに呼び出されるコールバック。エラーバウンダリにキャッチされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 + * **省略可能** `onUncaughtError`: エラーがスローされたがエラーバウンダリでキャッチされなかったときに呼び出されるコールバック。スローされた `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。 * **optional** `onRecoverableError`: React が自動的にエラーから回復したときに呼び出されるコールバック。React がスローする `error` と、`componentStack` を含んだ `errorInfo` を引数にして呼び出されます。復帰可能なエラーの一部は元のエラーを `error.cause` として含んでいます。 * **省略可能** `identifierPrefix`: React が [`useId`](/reference/react/useId) によって生成する ID に使用する文字列プレフィックス。同じページ上に複数のルートを使用する際に、競合を避けるために用います。サーバ上で使用されたものと同じプレフィックスでなければなりません。 @@ -376,12 +376,6 @@ export default function App({counter}) { ### キャッチされないエラーに対するダイアログを表示 {/*show-a-dialog-for-uncaught-errors*/} - - -`onUncaughtError` は最新版の React Canary リリースでのみ利用可能です。 - - - デフォルトでは React は、キャッチされなかったエラーをコンソールにログとして表示します。独自のエラーレポーティングを実装するには、省略可能なルートオプションである `onUncaughtError` を指定します。 ```js [[1, 7, "onUncaughtError"], [2, 7, "error", 1], [3, 7, "errorInfo"], [4, 11, "componentStack"]] @@ -612,28 +606,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*/} - - -`onCaughtError` は最新の React Canary リリースでのみ利用可能です。 - - - デフォルトでは、React はエラーバウンダリによってキャッチされたすべてのエラーを `console.error` に記録します。この動作をオーバーライドするには、省略可能なルートオプションである `onCaughtError` を指定して、[エラーバウンダリ](/reference/react/Component#catching-rendering-errors-with-an-error-boundary)によってキャッチされたエラーを処理するようにします。 ```js [[1, 7, "onCaughtError"], [2, 7, "error", 1], [3, 7, "errorInfo"], [4, 11, "componentStack"]] @@ -902,8 +879,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" }, @@ -1164,8 +1141,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 ca840df57..9f4b50147 100644 --- a/src/content/reference/react-dom/components/common.md +++ b/src/content/reference/react-dom/components/common.md @@ -246,43 +246,41 @@ title: "
    などの一般的なコンポーネント" [`useRef`](/reference/react/useRef#manipulating-the-dom-with-a-ref) などが返す ref オブジェクトの代わりに、`ref` 属性に関数を渡すことができます。 ```js -
    console.log(node)} /> +
    { + console.log('Attached', node); + + return () => { + console.log('Clean up', node) + } +}}> ``` [`ref` コールバックを使用した例を見る](/learn/manipulating-the-dom-with-refs#how-to-manage-a-list-of-refs-using-a-ref-callback) -`
    ` DOM ノードが画面に追加されると、React はその DOM `node` を引数として `ref` コールバックを呼び出します。`
    ` DOM ノードが削除されると、React は `null` を引数として `ref` コールバックを呼び出します。 +`
    ` DOM ノードが画面に追加されると、React はその DOM `node` を引数として `ref` コールバックを呼び出します。`
    ` DOM ノードが削除されると、React はコールバックが返したクリーンアップ関数を呼び出します。 React は、*異なる* `ref` コールバックが渡された場合も `ref` コールバックを呼び出します。上記の例では、`(node) => { ... }` は毎回のレンダーで異なる関数です。コンポーネントが再レンダーされると、*前*の関数が `null` を引数として呼び出され、*次*の関数が DOM ノードを引数として呼び出されます。 #### 引数 {/*ref-callback-parameters*/} -* `node`: DOM ノードまたは `null`。ref がアタッチされるときに React は DOM ノードを渡し、`ref` がデタッチされるときに `null` を渡します。毎回のレンダーで `ref` コールバックに同じ関数参照を渡さない限り、コールバックは一時的にデタッチされ、コンポーネントの再レンダーごとに再アタッチされます。 +* `node`: DOM ノード。ref がアタッチされるときに React は DOM ノードを渡します。毎回のレンダーで `ref` コールバックに同じ関数参照を渡さない限り、コンポーネントのレンダー毎に一時的なクリーンアップと再作成が繰り返されることになります。 - + -#### 返り値 {/*returns*/} +#### `ref` コールバックのクリーンアップは React 19 で追加されました {/*react-19-added-cleanup-functions-for-ref-callbacks*/} -* **省略可能** `cleanup function`: `ref` がデタッチされる際に React はこのクリーンアップ関数を実行します。`ref` コールバックから関数が返されない場合は、`ref` がデタッチされる際に `null` を引数にして元のコールバックの方を再度呼び出します。 +後方互換性をサポートするため、`ref` コールバックからクリーンアップ関数が返されない場合、`ref` がデタッチされると `node` を `null` としてコールバックが呼び出されます。この動作は将来のバージョンで削除される予定です。 -```js + -
    { - console.log(node); - - return () => { - console.log('Clean up', node) - } -}}> +#### 返り値 {/*returns*/} -``` +* **省略可能** クリーンアップ関数:`ref` がデタッチされると、React はクリーンアップ関数を呼び出します。ref コールバックが関数を返さない場合、ref がデタッチされたときに、React は null を引数として再度コールバックを呼び出しますが、この動作は将来のバージョンで削除される予定です。 #### 注意事項 {/*caveats*/} * Strict Mode が有効の場合、React は最終的なセットアップの前に、**開発時専用のセットアップ+クリーンアップのサイクルを追加で 1 回実行します**。これはクリーンアップのロジックがセットアップロジックに「鏡のように対応」しており、セットアップが行っていることが何であれそれの停止ないし取り消しを行っている、ということを保証するために行う、ストレステストです。問題が生じている場合は正しくクリーンアップ関数を実装してください。 -* *異なる* `ref` のコールバックを渡した場合、React は*古い*コールバックのクリーンアップが存在する場合それをまず実行します。クリーンアップ関数が定義されていない場合は、`ref` コールバック自体が `null` を引数にして呼び出されます。*新しい*関数は、DOM ノードを引数に呼び出されます。 - - +* *異なる* `ref` のコールバックを渡した場合、React は*古い*コールバックのクリーンアップが存在する場合それをまず実行します。クリーンアップ関数が定義されていない場合は、`ref` コールバック自体が `null` を引数にして呼び出されます。その後*新しい*関数が、DOM ノードを引数にして呼び出されます。 --- diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 04ac4e80d..9fded74e5 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -1,15 +1,7 @@ --- title: "
    " -canary: true --- - - -React による `` の機能拡張は、現在 React の Canary および experimental チャンネルでのみ利用可能です。React の安定版リリースでは、`` は単なる[組み込みのブラウザ HTML コンポーネント](https://react.dev/reference/react-dom/components#all-html-components)として機能します。[React のリリースチャンネルについてはこちらをご覧ください](/community/versioning-policy#all-release-channels)。 - - - - [ブラウザ組み込みの `` コンポーネント](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)を利用することで、情報を送信するためのインタラクティブなコントロールを作成できます。 @@ -77,27 +69,15 @@ 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": {} -} -``` - -### サーバアクションを使ってフォームの送信を処理する {/*handle-form-submission-with-a-server-action*/} +### サーバ関数を使ってフォームの送信を処理する {/*handle-form-submission-with-a-server-function*/} -`` をレンダーし、入力フィールドと送信ボタンを配置します。フォームが送信されたときに関数を実行するために、サーバアクション(Server Action; [`'use server'`](/reference/rsc/use-server) でマークされた関数)を form の `action` に渡します。 +`` をレンダーし、入力フィールドと送信ボタンを配置します。フォームが送信されたときに関数を実行するために、サーバ関数(Server Function; [`'use server'`](/reference/rsc/use-server) でマークされた関数)を form の `action` に渡します。 -`` にサーバアクションを渡すことで、JavaScript が無効あるいはコードがロードされる前の状態でも、ユーザがフォームを送信できるようになります。これは、接続やデバイスが遅い、または JavaScript が無効になっているユーザにとって有益であり、`action` に URL を渡したフォームと同様に動作します。 +`` にサーバ関数を渡すことで、JavaScript が無効あるいはコードがロードされる前の状態でも、ユーザがフォームを送信できるようになります。これは、接続やデバイスが遅い、または JavaScript が無効になっているユーザにとって有益であり、`action` に URL を渡したフォームと同様に動作します。 -`` のアクションには hidden となっているフォームフィールドを使ってデータを送信することもできます。サーバアクションは、hidden フィールドのデータも [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) インスタンスに含まれた状態で呼び出されます。 +`` のアクションには hidden となっているフォームフィールドを使ってデータを送信することもできます。サーバ関数は、hidden フィールドのデータも [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) インスタンスに含まれた状態で呼び出されます。 ```jsx import { updateCart } from './lib.js'; @@ -137,7 +117,7 @@ function AddToCart({productId}) { } ``` -[サーバコンポーネント](/reference/rsc/use-client) によって `` をレンダーし、`` の `action` に[サーバアクション](/reference/rsc/use-server)を渡すことで、フォームの[プログレッシブエンハンスメント](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement)が有効になります。 +[サーバコンポーネント](/reference/rsc/use-client) によって `` をレンダーし、`` の `action` に[サーバ関数](/reference/rsc/server-function)を渡すことで、フォームの[プログレッシブエンハンスメント](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement)が有効になります。 ### フォームの送信中状態を表示する {/*display-a-pending-state-during-form-submission*/} フォームが送信されている間に保留 (pending) 状態を表示するには、`` 内でレンダーされるコンポーネントで `useFormStatus` フックを呼び出して、返された `pending` プロパティを読み取ります。 @@ -178,17 +158,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` フックの詳細は[リファレンスドキュメント](/reference/react-dom/hooks/useFormStatus)を参照してください。 @@ -258,19 +227,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": {} -} -``` - [//]: # 'Uncomment the next line, and delete this line after the `useOptimistic` reference documentatino page is published' @@ -306,8 +262,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" }, @@ -323,10 +279,10 @@ export default function Search() { プログレッシブエンハンスメントの実現のため JavaScript バンドルが読み込まれる前にフォーム送信エラーメッセージを表示できるようにするには、以下の条件を満たす必要があります。 1. `` が [サーバコンポーネント](/reference/rsc/use-client)によってレンダーされている -1. `` の `action` プロパティに渡される関数が[サーバアクション](/reference/rsc/use-server)である +1. `` の `action` プロパティに渡される関数が[サーバ関数](/reference/rsc/server-functions)である 1. `useActionState` フックを使用してエラーメッセージを表示している -`useActionState` は[サーバアクション](/reference/rsc/use-server)と初期 state の 2 つの引数を受け取り、state 変数とアクションの 2 つの値を返します。`useActionState` が返したアクションは、フォームの `action` プロパティに渡します。`useActionState` が返した state 変数は、エラーメッセージを表示するために使用できます。`useActionState` に渡す[サーバアクション](/reference/rsc/use-server)が返す値は、state 変数を更新するために使用されます。 +`useActionState` は[サーバ関数](/reference/rsc/server-functions)と初期 state の 2 つの引数を受け取り、state 変数とアクションの 2 つの値を返します。`useActionState` が返したアクションは、フォームの `action` プロパティに渡します。`useActionState` が返した state 変数は、エラーメッセージを表示するために使用できます。`useActionState` に渡すサーバ関数が返す値は、state 変数を更新するために使用されます。 @@ -372,18 +328,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": {} -} -``` - フォームアクションから state を更新する方法については、[`useActionState`](/reference/react/useActionState) のドキュメントを参照してください。 @@ -420,16 +364,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 ab9e411ce..39f8b410f 100644 --- a/src/content/reference/react-dom/components/input.md +++ b/src/content/reference/react-dom/components/input.md @@ -32,12 +32,7 @@ title: "" `` は[一般的な要素の props](/reference/react-dom/components/common#props) をすべてサポートしています。 - - -`formAction` に対する React の拡張は React の Canary および experimental リリースのみの機能です。React の安定版では `formAction` は[組み込みブラウザコンポーネント](/reference/react-dom/components#all-html-components)の機能としてのみ動作します。[React のリリースチャンネルについてはこちら](/community/versioning-policy#all-release-channels)。 - - -[`formAction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formaction): 文字列または関数。`type="submit"` and `type="image"` の場合に親の `` を上書きする。`action` に URL が渡された場合はフォームは標準的な HTML フォームとして動作する。関数が渡された場合はその関数がフォームの送信を処理する。[``](/reference/react-dom/components/form#props) を参照。 +- [`formAction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formaction): 文字列または関数。`type="submit"` and `type="image"` の場合に親の `` を上書きする。`action` に URL が渡された場合はフォームは標準的な HTML フォームとして動作する。関数が渡された場合はその関数がフォームの送信を処理する。[``](/reference/react-dom/components/form#props) を参照。 以下の props を渡すことで、[入力欄を制御されたコンポーネント (controlled component)](#controlling-an-input-with-a-state-variable) にできます。 diff --git a/src/content/reference/react-dom/components/link.md b/src/content/reference/react-dom/components/link.md index 3bfdf71c4..af7a84fd8 100644 --- a/src/content/reference/react-dom/components/link.md +++ b/src/content/reference/react-dom/components/link.md @@ -1,14 +1,7 @@ --- link: "" -canary: true --- - - -React による `` の機能拡張は、現在 React の Canary および experimental チャンネルでのみ利用可能です。React の安定版リリースでは、`` は単なる[組み込みのブラウザ HTML コンポーネント](https://react.dev/reference/react-dom/components#all-html-components)として機能します。[React のリリースチャンネルについてはこちらをご覧ください](/community/versioning-policy#all-release-channels)。 - - - [ブラウザ組み込みの `` コンポーネント](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 daf19ba68..df06eae62 100644 --- a/src/content/reference/react-dom/components/meta.md +++ b/src/content/reference/react-dom/components/meta.md @@ -1,15 +1,7 @@ --- meta: "" -canary: true --- - - -React による `` の機能拡張は、現在 React の Canary および experimental チャンネルでのみ利用可能です。React の安定版リリースでは、`` は単なる[組み込みのブラウザ HTML コンポーネント](https://react.dev/reference/react-dom/components#all-html-components)として機能します。[React のリリースチャンネルについてはこちらをご覧ください](/community/versioning-policy#all-release-channels)。 - - - - [ブラウザ組み込みの `` コンポーネント](https://developer.mozilla.org/en-US/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 a599cc6c6..73eb6a19a 100644 --- a/src/content/reference/react-dom/components/script.md +++ b/src/content/reference/react-dom/components/script.md @@ -1,14 +1,7 @@ --- script: " +``` + +クライアント側では、ブートストラップスクリプトは [`hydrateRoot` を呼び出して `document` 全体のハイドレーションを行う](/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, ); +``` + +これにより、サーバで生成された静的な HTML にイベントリスナが追加され、操作可能になります。 + + + +#### ビルド出力から CSS と JS のアセットパスを読み取る {/*reading-css-and-js-asset-paths-from-the-build-output*/} + +ビルド後に、最終的なアセット URL(JavaScript や CSS ファイルなど)にはよくハッシュ化が行われます。例えば、`styles.css` が `styles.123456.css` になることがあります。静的なアセットのファイル名をハッシュ化することで、同じアセットがビルドごとに異なるファイル名になることが保証されます。これが有用なのは、ある特定の名前を持つファイルの内容が不変になり、静的なアセットの長期的なキャッシングを安全に行えるようになるためです。 + +しかし、ビルド後までアセット URL が分からない場合、それらをソースコードに含めることができません。例えば、先ほどのように JSX に `"/styles.css"` をハードコーディングする方法は動作しません。ソースコードにそれらを含めないようにするため、ルートコンポーネントが、props 経由で渡されたマップから実際のファイル名を読み取るようにすることができます。 + +```js {1,6} +export default function App({ assetMap }) { + return ( + + + My app + + + ... + + ); +} +``` + +サーバ上では、`` のようにレンダーし、アセット URL を含む `assetMap` を渡します。 + +```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' }, + }); +} +``` + +サーバで `` のようにレンダーしているので、クライアントでも `assetMap` を使ってレンダーしてハイドレーションエラーを避ける必要があります。このためには以下のように `assetMap` をシリアライズしてクライアントに渡します。 + +```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' }, + }); +} +``` + +上記の例では、`bootstrapScriptContent` オプションを使って` +``` + +クライアント側では、ブートストラップスクリプトは [`hydrateRoot` を呼び出して `document` 全体のハイドレーションを行う](/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, ); +``` + +これにより、サーバで生成された静的な HTML にイベントリスナが追加され、操作可能になります。 + + + +#### ビルド出力から CSS と JS のアセットパスを読み取る {/*reading-css-and-js-asset-paths-from-the-build-output*/} + +ビルド後に、最終的なアセット URL(JavaScript や CSS ファイルなど)にはよくハッシュ化が行われます。例えば、`styles.css` が `styles.123456.css` になることがあります。静的なアセットのファイル名をハッシュ化することで、同じアセットがビルドごとに異なるファイル名になることが保証されます。これが有用なのは、ある特定の名前を持つファイルの内容が不変になり、静的なアセットの長期的なキャッシングを安全に行えるようになるためです。 + +しかし、ビルド後までアセット URL が分からない場合、それらをソースコードに含めることができません。例えば、先ほどのように JSX に `"/styles.css"` をハードコーディングする方法は動作しません。ソースコードにそれらを含めないようにするため、ルートコンポーネントが、props 経由で渡されたマップから実際のファイル名を読み取るようにすることができます。 + +```js {1,6} +export default function App({ assetMap }) { + return ( + + + My app + + + ... + + ); +} +``` + +サーバ上では、`` のようにレンダーし、アセット URL を含む `assetMap` を渡します。 + +```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); +}); +``` + +サーバで `` のようにレンダーしているので、クライアントでも `assetMap` を使ってレンダーしてハイドレーションエラーを避ける必要があります。このためには以下のように `assetMap` をシリアライズしてクライアントに渡します。 + +```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); +}); +``` + +上記の例では、`bootstrapScriptContent` オプションを使って`