reactjsnext.jsreact-server-components

When to use the 'use server' directive


The example in https://react.dev/reference/rsc/server-components#async-components-with-server-components shows the following snippet:

// Server Component
import db from './database';

async function Page({id}) {
  // Will suspend the Server Component.
  const note = await db.notes.get(id);
  
  // NOTE: not awaited, will start here and await on the client. 

  //****NO 'use server' USED HERE!****

  const commentsPromise = db.comments.get(note.id);
  return (
    <div>
      {note}
      <Suspense fallback={<p>Loading Comments...</p>}>
        <Comments commentsPromise={commentsPromise} />
      </Suspense>
    </div>
  );
}

// Client Component
"use client";
import {use} from 'react';

function Comments({commentsPromise}) {
  // NOTE: this will resume the promise from the server.
  // It will suspend until the data is available.
  const comments = use(commentsPromise);
  return comments.map(commment => <p>{comment}</p>);
}

There is no 'use server' above the call to db.comments.get(note.id) in the server component.

However on https://react.dev/reference/rsc/server-functions, it shows this snippet:

// Server Component
import Button from './Button';

function EmptyNote () {
  async function createNoteAction() {
    // Server Function
    'use server';
    
    await db.notes.create();
  }

  return <Button onClick={createNoteAction}/>;
}

"use client";

export default function Button({onClick}) { 
  console.log(onClick); 
  // {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
  return <button onClick={() => onClick()}>Create Empty Note</button>
}

Why is 'use server' used in the last snippet but not the first snippet?


Solution

  • Thanks to the active ReactJS community on Reddit, I got an answer:

    'use server' can be thought of as setting up an API. So in the second snippet, the Button which is rendered on the client is set up so that an HTTP request is made to the server to create the note, just like an API call.

    However, in the first snippet, there's no need to wait for the user to click the button to do something on the server. It starts the DB query on the server and and returns a promise inside the RSC payload which is sent to the client.

    The client then has information about this promise and the server streams the data to the client.