添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

React Server Components

'use client' is for use with React Server Components .

'use client' lets you mark what code runs on the client.

Reference

'use client'

Add 'use client' at the top of a file to mark the module and its transitive dependencies as client code.

'use client';

import { useState } from 'react';
import { formatDate } from './formatters';
import Button from './button';

export default function RichTextEditor({ timestamp, text }) {
const date = formatDate(timestamp);
// ...
const editButton = <Button />;
// ...
}

When a file marked with 'use client' is imported from a Server Component, compatible bundlers will treat the module import as a boundary between server-run and client-run code.

As dependencies of RichTextEditor , formatDate and Button will also be evaluated on the client regardless of whether their modules contain a 'use client' directive. Note that a single module may be evaluated on the server when imported from server code and on the client when imported from client code.

Caveats

  • 'use client' must be at the very beginning of a file, above any imports or other code (comments are OK). They must be written with single or double quotes, but not backticks.
  • When a 'use client' module is imported from another client-rendered module, the directive has no effect.
  • When a component module contains a 'use client' directive, any usage of that component is guaranteed to be a Client Component. However, a component can still be evaluated on the client even if it does not have a 'use client' directive.
  • A component usage is considered a Client Component if it is defined in module with 'use client' directive or when it is a transitive dependency of a module that contains a 'use client' directive. Otherwise, it is a Server Component.
  • Code that is marked for client evaluation is not limited to components. All code that is a part of the Client module sub-tree is sent to and run by the client.
  • When a server evaluated module imports values from a 'use client' module, the values must either be a React component or supported serializable prop values to be passed to a Client Component. Any other use case will throw an exception.
  • How 'use client' marks client code

    In a React app, components are often split into separate files, or modules .

    For apps that use React Server Components, the app is server-rendered by default. 'use client' introduces a server-client boundary in the module dependency tree , effectively creating a subtree of Client modules.

    To better illustrate this, consider the following React Server Components app.

    import InspirationGenerator from './InspirationGenerator' ; export default function App ( ) { return ( < FancyText title text = "Get Inspired App" /> < InspirationGenerator > </ InspirationGenerator >

    In the module dependency tree of this example app, the 'use client' directive in InspirationGenerator.js marks that module and all of its transitive dependencies as Client modules. The subtree starting at InspirationGenerator.js is now marked as Client modules.

    A tree graph with the top node representing the module 'App.js'. 'App.js' has three children: 'Copyright.js', 'FancyText.js', and 'InspirationGenerator.js'. 'InspirationGenerator.js' has two children: 'FancyText.js' and 'inspirations.js'. The nodes under and including 'InspirationGenerator.js' have a yellow background color to signify that this sub-graph is client-rendered due to the 'use client' directive in 'InspirationGenerator.js'.
    A tree graph with the top node representing the module 'App.js'. 'App.js' has three children: 'Copyright.js', 'FancyText.js', and 'InspirationGenerator.js'. 'InspirationGenerator.js' has two children: 'FancyText.js' and 'inspirations.js'. The nodes under and including 'InspirationGenerator.js' have a yellow background color to signify that this sub-graph is client-rendered due to the 'use client' directive in 'InspirationGenerator.js'.

    'use client' segments the module dependency tree of the React Server Components app, marking InspirationGenerator.js and all of its dependencies as client-rendered.

    During render, the framework will server-render the root component and continue through the render tree , opting-out of evaluating any code imported from client-marked code.

    The server-rendered portion of the render tree is then sent to the client. The client, with its client code downloaded, then completes rendering the rest of the tree.

    A tree graph where each node represents a component and its children as child components. The top-level node is labelled 'App' and it has two child components 'InspirationGenerator' and 'FancyText'. 'InspirationGenerator' has two child components, 'FancyText' and 'Copyright'. Both 'InspirationGenerator' and its child component 'FancyText' are marked to be client-rendered.
    A tree graph where each node represents a component and its children as child components. The top-level node is labelled 'App' and it has two child components 'InspirationGenerator' and 'FancyText'. 'InspirationGenerator' has two child components, 'FancyText' and 'Copyright'. Both 'InspirationGenerator' and its child component 'FancyText' are marked to be client-rendered.

    The render tree for the React Server Components app. InspirationGenerator and its child component FancyText are components exported from client-marked code and considered Client Components.

    We introduce the following definitions:

  • Client Components are components in a render tree that are rendered on the client.
  • Server Components are components in a render tree that are rendered on the server.
  • Deep Dive

    How is FancyText both a Server and a Client Component?

    By the above definitions, the component FancyText is both a Server and Client Component, how can that be?

    First, let’s clarify that the term “component” is not very precise. Here are just two ways “component” can be understood:

    1. A “component” can refer to a component definition . In most cases this will be a function.
    // This is a definition of a component
    function MyComponent() {
    return <p>My Component</p>
    }
    1. A “component” can also refer to a component usage of its definition.
    import MyComponent from './MyComponent';

    function App() {
    // This is a usage of a component
    return <MyComponent />;
    }

    Often, the imprecision is not important when explaining concepts, but in this case it is.

    When we talk about Server or Client Components, we are referring to component usages.

    • If the component is defined in a module with a 'use client' directive, or the component is imported and called in a Client Component, then the component usage is a Client Component.
    • Otherwise, the component usage is a Server Component.
    A tree graph where each node represents a component and its children as child components. The top-level node is labelled 'App' and it has two child components 'InspirationGenerator' and 'FancyText'. 'InspirationGenerator' has two child components, 'FancyText' and 'Copyright'. Both 'InspirationGenerator' and its child component 'FancyText' are marked to be client-rendered.
    A tree graph where each node represents a component and its children as child components. The top-level node is labelled 'App' and it has two child components 'InspirationGenerator' and 'FancyText'. 'InspirationGenerator' has two child components, 'FancyText' and 'Copyright'. Both 'InspirationGenerator' and its child component 'FancyText' are marked to be client-rendered.
    A render tree illustrates component usages.

    Back to the question of FancyText , we see that the component definition does not have a 'use client' directive and it has two usages.

    The usage of FancyText as a child of App , marks that usage as a Server Component. When FancyText is imported and called under InspirationGenerator , that usage of FancyText is a Client Component as InspirationGenerator contains a 'use client' directive.

    This means that the component definition for FancyText will both be evaluated on the server and also downloaded by the client to render its Client Component usage.

    When to use 'use client'

    With 'use client' , you can determine when components are Client Components. As Server Components are default, here is a brief overview of the advantages and limitations to Server Components to determine when you need to mark something as client rendered.

    For simplicity, we talk about Server Components, but the same principles apply to all code in your app that is server run.

    Advantages of Server Components

  • Server Components can reduce the amount of code sent and run by the client. Only Client modules are bundled and evaluated by the client.
  • Server Components benefit from running on the server. They can access the local filesystem and may experience low latency for data fetches and network requests.
  • Limitations of Server Components

  • Server Components cannot support interaction as event handlers must be registered and triggered by a client.
  • For example, event handlers like onClick can only be defined in Client Components.
  • Server Components cannot use most Hooks.
  • When Server Components are rendered, their output is essentially a list of components for the client to render. Server Components do not persist in memory after render and cannot have their own state.
  • Serializable types returned by Server Components

    As in any React app, parent components pass data to child components. As they are rendered in different environments, passing data from a Server Component to a Client Component requires extra consideration.

    Prop values passed from a Server Component to Client Component must be serializable.

    Serializable props include:

  • Primitives
  • string
  • number
  • bigint
  • boolean
  • undefined
  • symbol , only symbols registered in the global Symbol registry via Symbol.for
  • Iterables containing serializable values
  • String
  • Array
  • TypedArray and ArrayBuffer
  • Plain objects : those created with object initializers , with serializable properties
  • Functions that are Server Functions
  • Client or Server Component elements (JSX)
  • Promises
  • Notably, these are not supported:

  • Functions that are not exported from client-marked modules or marked with 'use server'
  • Classes
  • Objects that are instances of any class (other than the built-ins mentioned) or objects with a null prototype
  • Symbols not registered globally, ex. Symbol('my new symbol')
  • Usage

    Building with interactivity and state

    'use client';
    import { useState } from 'react';
    export default function Counter({initialValue = 0}) {
      const [countValue, setCountValue] = useState(initialValue);
      const increment = () => setCountValue(countValue + 1);
      const decrement = () => setCountValue(countValue - 1);
      return (
          <h2>Count Value: {countValue}</h2>
          <button onClick={increment}>+1</button>
          <button onClick={decrement}>-1</button>