How Do ‘use client’ and ‘use server’ Transform React’s Module System?
This article explains the purpose and mechanics of the new React directives ‘use client’ and ‘use server’, showing how they let developers express client‑server boundaries directly in the module system, turn server functions into type‑safe RPC calls, and embed client components as scripts for seamless full‑stack integration.
This article, translated from Dan’s post “What Does ‘use client’ Do?”, explains the new directives ‘use client’ and ‘use server’ in React and how they reshape the interaction between frontend and backend code.
use server
‘use server’ marks exported functions as server‑only, turning them into type‑safe, statically analysable remote‑procedure calls. The article shows a typical backend API with async functions likePost and unlikePost, then demonstrates importing them in frontend code where they become async functions that perform fetch requests.
async function likePost(postId) {
const userId = getCurrentUser();
await db.likes.create({ postId, userId });
const count = await db.likes.count({ where: { postId } });
return { likes: count };
}
async function unlikePost(postId) {
const userId = getCurrentUser();
await db.likes.destroy({ where: { postId, userId } });
const count = await db.likes.count({ where: { postId } });
return { likes: count };
}Using ‘use server’ lets the module system express the client‑server boundary directly, enabling tooling such as “find all references” and dead‑code elimination.
use client
‘use client’ marks a module as client‑side. When a server file imports a client component (e.g., a LikeButton component), the server receives a client reference that is rendered as a <script> tag. The component can then be used in JSX on the server, producing HTML that includes the script and optional pre‑rendered markup.
export function LikeButton({ postId, likeCount, isLiked }) {
function handleClick() {
// client‑side interaction logic
}
return (
<button className={isLiked ? 'liked' : ''}>
{likeCount} Likes
</button>
);
}Two worlds, two doors
The two directives are not simple tags for “client” or “server” code; they open doors between the two runtimes. ‘use server’ exports functions that the client can call via HTTP, while ‘use client’ exports components that the server can embed as scripts, allowing a single program to span both environments.
Both directives acknowledge that the client and server do not share an execution context, so imports do not execute code but merely reference code in the opposite environment, enabling a seamless, type‑safe, and modular full‑stack development experience.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
