diff --git a/src/components/Layout/getRouteMeta.tsx b/src/components/Layout/getRouteMeta.tsx index d22947847a..3564dd7385 100644 --- a/src/components/Layout/getRouteMeta.tsx +++ b/src/components/Layout/getRouteMeta.tsx @@ -58,13 +58,13 @@ export interface RouteMeta { order?: number; } -type TravesalContext = RouteMeta & { +type TraversalContext = RouteMeta & { currentIndex: number; }; export function getRouteMeta(cleanedPath: string, routeTree: RouteItem) { const breadcrumbs = getBreadcrumbs(cleanedPath, routeTree); - const ctx: TravesalContext = { + const ctx: TraversalContext = { currentIndex: 0, }; buildRouteMeta(cleanedPath, routeTree, ctx); @@ -79,7 +79,7 @@ export function getRouteMeta(cleanedPath: string, routeTree: RouteItem) { function buildRouteMeta( searchPath: string, currentRoute: RouteItem, - ctx: TravesalContext + ctx: TraversalContext ) { ctx.currentIndex++; diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 7c60232207..dfffc74f56 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -273,7 +273,7 @@ export async function deliverMessage(message) { -[//]: # 'Uncomment the next line, and delete this line after the `useOptimisitc` reference documentatino page is published' +[//]: # 'Uncomment the next line, and delete this line after the `useOptimistic` reference documentatino page is published' [//]: # 'To learn more about the `useOptimistic` Hook see the [reference documentation](/reference/react/hooks/useOptimistic).' ### Handling form submission errors {/*handling-form-submission-errors*/} diff --git a/src/content/reference/react/use-client.md b/src/content/reference/react/use-client.md index 3386364be5..b824235147 100644 --- a/src/content/reference/react/use-client.md +++ b/src/content/reference/react/use-client.md @@ -32,20 +32,19 @@ Add `'use client'` at the top of a file to mark the module and its transitive de import { useState } from 'react'; import { formatDate } from './formatters'; -import Link from './link'; +import Button from './button'; -export default function RichTextEditor(props) { - formatDate(); +export default function RichTextEditor({ timestamp, text }) { + const date = formatDate(timestamp); + // ... + const editButton = - - ); + const [countValue, setCountValue] = useState(initialValue); + const increment = () => setCountValue(countValue + 1); + const decrement = () => setCountValue(countValue - 1); + return ( + <> +

Count Value: {countValue}

+ + + + ); } ``` @@ -312,18 +313,18 @@ As `Counter` requires both the `useState` hook and event handlers to increment o In contrast, a component that renders UI without interaction will not need to be a Client Component. ```js -import {getCounterValueFromFile} from 'fs-utils'; +import { readFile } from 'node:fs/promises'; import Counter from './Counter'; export default async function CounterContainer() { - const initialValue = await getCounterValueFromFile(); + const initialValue = await readFile('/path/to/counter_value'); return } ``` -For example, the parent component of the Client Component `CounterContainer` does not require `'use client'` as it is not interactive and does not use state. In addition, `CounterContainer` must be a Server Component as it reads from the local file system on the server. This is possible because Server Components, unlike Client Components, can be async functions. +For example, `Counter`'s parent component, `CounterContainer`, does not require `'use client'` as it is not interactive and does not use state. In addition, `CounterContainer` must be a Server Component as it reads from the local file system on the server, which is possible only in a Server Component. -There are also components that don't use any server or client-only features and can be agnostic to where they render. `FancyText` is an example of such a component. +There are also components that don't use any server or client-only features and can be agnostic to where they render. In our earlier example, `FancyText` is one such component. ```js export default function FancyText({title, text}) { @@ -333,13 +334,15 @@ export default function FancyText({title, text}) { } ``` -In this case, it is discouraged to use the `'use client'` directive as it prematurely forces all component usages of `FancyText` to be rendered on the client, which comes at a performance cost. As demonstrated in the earlier Inspirations app example, `FancyText` is used as both a Server or Client Component, depending on where it is imported and used. +In this case, we don't add the `'use client'` directive, resulting in `FancyText`'s _output_ (rather than its source code) to be sent to the browser when referenced from a Server Component. As demonstrated in the earlier Inspirations app example, `FancyText` is used as both a Server or Client Component, depending on where it is imported and used. + +But if `FancyText`'s HTML output was large relative to its source code (including dependencies), it might be more efficient to force it to always be a Client Component. Components that return a long SVG path string are one case where it may be more efficient to force a component to be a Client Component. ### Using client APIs {/*using-client-apis*/} -Your React app may use client-specific APIs which are dependent on your targeted client. For the browser, some example client APIs include web storage, audio and video manipulation, and device hardware, among [others](https://developer.mozilla.org/en-US/docs/Web/API). +Your React app may use client-specific APIs, such as the browser's APIs for web storage, audio and video manipulation, and device hardware, among [others](https://developer.mozilla.org/en-US/docs/Web/API). -In this example, the component uses [DOM APIs](https://developer.mozilla.org/en-US/docs/Glossary/DOM) to manipulate a [`canvas`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas) element. Since those APIs are only available in the browser, it must be marked as a Client Component. +In this example, the component uses [DOM APIs](https://developer.mozilla.org/en-US/docs/Glossary/DOM) to manipulate a [`canvas`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas) element. Since those APIs are only available in the browser, it must be marked as a Client Component. ```js 'use client'; @@ -351,21 +354,20 @@ export default function Circle() { useLayoutEffect(() => { const canvas = ref.current; const context = canvas.getContext('2d'); + context.reset(); context.beginPath(); context.arc(100, 75, 50, 0, 2 * Math.PI); context.stroke(); }); - return + return ; } ``` -### Using React libraries {/*using-react-libraries*/} +### Using third-party libraries {/*using-third-party-libraries*/} Often in a React app, you'll leverage third-party libraries to handle common UI patterns or logic. -These libraries may rely on component Hooks or client APIs. In these cases, you'll need to ensure you're using these libraries in Client Components. Depending on the nature of these libraries, this may mean adding a `'use client'` near the top of your module dependency tree – marking the majority of your React app as client-rendered. - -Libraries that use any of the following React APIs must be marked as client-run: +These libraries may rely on component Hooks or client APIs. Third-party components that use any of the following React APIs must run on the client: * [createContext](/reference/react/createContext) * [`react`](/reference/react/hooks) and [`react-dom`](/reference/react-dom/hooks) Hooks, excluding [`use`](/reference/react/use) and [`useId`](/reference/react/useId) * [forwardRef](/reference/react/forwardRef) @@ -373,4 +375,6 @@ Libraries that use any of the following React APIs must be marked as client-run: * [startTransition](/reference/react/startTransition) * If they use client APIs, ex. DOM insertion or native platform views +If these libraries have been updated to be compatible with React Server Components, then they will already include `'use client'` markers of their own, allowing you to use them directly from your Server Components. If a library hasn't been updated, or if a component needs props like event handlers that can only be specified on the client, you may need to add your own Client Component file in between the third-party Client Component and your Server Component where you'd like to use it. + [TODO]: <> (Troubleshooting - need use-cases) diff --git a/src/content/reference/react/use-server.md b/src/content/reference/react/use-server.md index 45703db40d..3cf1d212b8 100644 --- a/src/content/reference/react/use-server.md +++ b/src/content/reference/react/use-server.md @@ -80,8 +80,7 @@ Here are supported types for server action arguments: * [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) * [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) * [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) - * [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) -* [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) + * [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) and [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) * [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) * [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) instances * Plain [objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object): those created with [object initializers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer), with serializable properties @@ -92,7 +91,7 @@ Notably, these are not supported: * React elements, or [JSX](https://react.dev/learn/writing-markup-with-jsx) * Functions, including component functions or any other function that is not a server action * [Classes](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Classes_in_JavaScript) -* Objects that are instances of any class (other than built-ins mentioned) or objects with [null-prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#null-prototype_objects) +* Objects that are instances of any class (other than the built-ins mentioned) or objects with [a null prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#null-prototype_objects) * Symbols not registered globally, ex. `Symbol('my new symbol')`