diff --git a/src/content/reference/rsc/use-client.md b/src/content/reference/rsc/use-client.md index 4c6051977ef..813693230ba 100644 --- a/src/content/reference/rsc/use-client.md +++ b/src/content/reference/rsc/use-client.md @@ -376,4 +376,96 @@ These libraries may rely on component Hooks or client APIs. Third-party componen 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) +## Troubleshooting {/*troubleshooting*/} + +### "Functions cannot be passed directly to Client Components" error {/*functions-cannot-be-passed-directly*/} + +This error occurs when you try to pass a function from a Server Component to a Client Component. + +```js +// Server Component +import ClientButton from './ClientButton'; + +export default function Page() { + function handleClick() { + console.log('clicked'); + } + // This will error! + return ; +} +``` + +Functions are not serializable, so they cannot be passed from server to client. To fix this, either move the function to the Client Component, or use a [Server Function](/reference/rsc/server-functions) with `'use server'`. + +```js +// Solution 1: Move the handler to the Client Component +'use client'; + +export default function ClientButton() { + function handleClick() { + console.log('clicked'); + } + return ; +} +``` + +```js +// Solution 2: Use a Server Function +'use server'; + +export async function handleClick() { + console.log('clicked on server'); +} +``` + +### Component uses hooks but doesn't have `'use client'` {/*component-uses-hooks-without-use-client*/} + +If you're using hooks like `useState`, `useEffect`, or `useContext` in a component, you need to mark it as a Client Component. + +```js +// This will error - hooks require 'use client' +import { useState } from 'react'; + +export default function Counter() { + const [count, setCount] = useState(0); + return ; +} +``` + +Add `'use client'` at the top of the file: + +```js +'use client'; + +import { useState } from 'react'; + +export default function Counter() { + const [count, setCount] = useState(0); + return ; +} +``` + +### Third-party library doesn't work in Server Components {/*third-party-library-server-component*/} + +Many third-party libraries were written before Server Components existed and may use client-only features. If you get an error when importing a library in a Server Component, create a wrapper Client Component: + +```js +// components/ChartWrapper.js +'use client'; + +import { Chart } from 'third-party-chart-library'; + +export default function ChartWrapper(props) { + return ; +} +``` + +Then import the wrapper in your Server Component: + +```js +// page.js (Server Component) +import ChartWrapper from './components/ChartWrapper'; + +export default function Page() { + return ; +} diff --git a/src/content/reference/rsc/use-server.md b/src/content/reference/rsc/use-server.md index 359637aa7dc..cb4f90a9e81 100644 --- a/src/content/reference/rsc/use-server.md +++ b/src/content/reference/rsc/use-server.md @@ -215,3 +215,97 @@ export default async function incrementLike() { ``` To read a Server Function return value, you'll need to `await` the promise returned. + +## Troubleshooting {/*troubleshooting*/} + +### "Server Functions cannot be called during render" error {/*server-functions-cannot-be-called-during-render*/} + +Server Functions should only be called in response to user actions (like form submissions or button clicks), not during component rendering. + +```js +// This will error - calling during render +function BadComponent() { + const data = await serverFunction(); // Don't do this! + return
{data}
; +} + +// Correct - call in response to user action +function GoodComponent() { + const [data, setData] = useState(null); + + const handleClick = async () => { + const result = await serverFunction(); + setData(result); + }; + + return ; +} +``` + +For data fetching during render, use a Server Component instead of a Server Function. + +### "Arguments must be serializable" error {/*arguments-must-be-serializable*/} + +Server Functions can only receive serializable arguments. You cannot pass functions, class instances, or React elements. + +```js +// This will error - functions aren't serializable +async function saveData(callback) { + 'use server'; + // ... +} + +// Correct - pass serializable data +async function saveData(userId, formData) { + 'use server'; + // ... +} +``` + +### Server Function not updating the UI {/*server-function-not-updating-ui*/} + +If your Server Function runs but the UI doesn't update, make sure you're calling it inside a Transition when outside a form: + +```js +import { useTransition } from 'react'; + +function MyComponent() { + const [isPending, startTransition] = useTransition(); + + const handleClick = () => { + // Wrap in startTransition for proper UI updates + startTransition(async () => { + await myServerFunction(); + }); + }; + + return ; +} +``` + +### "use server" directive not working {/*use-server-directive-not-working*/} + +The `'use server'` directive must be: +1. At the very beginning of the function body (not before the function) +2. Written with single or double quotes (not backticks) +3. Used only in async functions + +```js +// Wrong - directive before function +'use server'; +async function myFunction() { + // ... +} + +// Correct - directive inside function body +async function myFunction() { + 'use server'; + // ... +} + +// Also correct - at top of file to mark all exports +'use server'; + +export async function functionA() { /* ... */ } +export async function functionB() { /* ... */ } +```