useClient
and useServer
are React hooks introduced in Next.js to optimize and clarify the execution context of components or logic within an application. These hooks are part of Next.js’s ongoing enhancements to support React Server Components, enabling developers to specify more clearly whether a component should run on the client-side or server-side.
useServer
The useServer
hook is a clear indication that the enclosed code or component is intended to run only on the server. This is particularly useful for operations that are sensitive or need direct access to server-side resources such as databases or environment variables that should not be exposed to the client. Here’s a quick example:
'use server' function ServerComponent() { const data = useServer(() => { // Fetch data or perform operations that are server-only return fetchSecretData(); }); return <div>Secret Data: {data}</div>; }
import { useServer } from 'next/server'; function ServerComponent() { const serverData = useServer(() => { // Simulate fetching server-only data const data = fetchServerData(); return data; }); return <div>Loaded server-only data: {serverData}</div>; } function fetchServerData() { // Pretend to fetch data that should not be exposed to the client return "Secret server info"; }
In this example, fetchSecretData
is a function that you wouldn’t want to expose to the client-side due to security concerns or computational reasons. By using useServer
, you ensure that this function only runs on the server.
useClient
Conversely, useClient
is used to denote that the enclosed code or component should run only on the client-side. This is suitable for interactions that depend solely on the browser’s capabilities, such as DOM manipulations or client-side state handling that doesn’t need to pre-render on the server. Here’s how you might use it:
'use client' function ClientComponent() { const [count, setCount] = useClient(() => { // Only run this hook in the client-side environment const [localCount, setLocalCount] = useState(0); return [localCount, setLocalCount]; }); return ( <div> <button onClick={() => setCount(count + 1)}>Increment</button> Count: {count} </div> ); }
import { useClient } from 'next/client'; import { useState } from 'react'; function ClientComponent() { const [count, setCount] = useClient(() => { // Initialize state only on the client const [localCount, setLocalCount] = useState(0); return [localCount, setLocalCount]; }); // Button click handler for incrementing the count function handleClick() { setCount(count + 1); } return ( <div> <button onClick={handleClick}>Increment</button> Count: {count} </div> ); }
In this example, the state management for count
is purely client-side, which makes useClient
ideal for encapsulating client-specific logic.
When to Use useServer
vs. useClient
Deciding whether to use useServer
or useClient
boils down to understanding where your code needs to execute for optimal performance and security. Here are some guidelines:
- Use
useServer
if:- You need to access server-side resources or perform actions securely, away from the client’s reach.
- You want to pre-render data or perform computations during server-side rendering (SSR) for SEO benefits or faster page loads.
- Use
useClient
if:- Your component or logic must interact with browser-specific APIs or client-side resources like the local storage.
- You are handling state or effects that should only occur in the client’s environment, such as animations or user input events.