Skip to content

Commit a3078ca

Browse files
author
sunilsonumonu12
committed
do
1 parent 3a3374d commit a3078ca

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

src/content/reference/rsc/server-components.md

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ The bundler then combines the data, rendered Server Components and dynamic Clien
183183
</div>
184184
```
185185

186-
Server Components can be made dynamic by re-fetching them from a server, where they can access the data and render again. This new application architecture combines the simple request/response mental model of server-centric Multi-Page Apps with the seamless interactivity of client-centric Single-Page Apps, giving you the best of both worlds.
186+
Server Components can be made dynamic by re-fetching them from a server, where they can access the data and render again. This new application architecture combines the simple "request/response" mental model of server-centric Multi-Page Apps with the seamless interactivity of client-centric Single-Page Apps, giving you the best of both worlds.
187187

188188
### Adding interactivity to Server Components {/*adding-interactivity-to-server-components*/}
189189

@@ -300,3 +300,55 @@ function Comments({commentsPromise}) {
300300
The `note` content is important data for the page to render, so we `await` it on the server. The comments are below the fold and lower-priority, so we start the promise on the server, and wait for it on the client with the `use` API. This will Suspend on the client, without blocking the `note` content from rendering.
301301

302302
Since async components are not supported on the client, we await the promise with `use`.
303+
304+
<Note>
305+
306+
#### Alternative: Manual Promise handling in Client Components {/*alternative-manual-promise-handling*/}
307+
308+
While the `use()` hook provides seamless integration with Suspense boundaries, you can also handle Promises manually in Client Components using traditional React patterns with `useEffect` and `useState`. This approach gives you more control over loading states and error handling:
309+
310+
```js
311+
// Client Component
312+
"use client";
313+
import { useState, useEffect } from 'react';
314+
315+
function Comments({commentsPromise}) {
316+
const [comments, setComments] = useState(null);
317+
const [error, setError] = useState(null);
318+
319+
useEffect(() => {
320+
let cancelled = false;
321+
322+
commentsPromise
323+
.then(data => {
324+
if (!cancelled) {
325+
setComments(data);
326+
}
327+
})
328+
.catch(err => {
329+
if (!cancelled) {
330+
setError(err);
331+
}
332+
});
333+
334+
return () => {
335+
cancelled = true;
336+
};
337+
}, [commentsPromise]);
338+
339+
if (error) return <p>Error loading comments: {error.message}</p>;
340+
if (!comments) return <p>Loading comments...</p>;
341+
342+
return comments.map(comment => <p key={comment.id}>{comment.text}</p>);
343+
}
344+
```
345+
346+
This pattern is useful when you need:
347+
- Custom loading indicators without Suspense boundaries
348+
- Granular error handling at the component level
349+
- To update parts of the UI progressively as data arrives
350+
- To maintain existing component patterns while adopting Server Components
351+
352+
Both approaches are valid. Choose `use()` for simpler code that works with Suspense, or manual handling when you need more control over the loading experience.
353+
354+
</Note>

0 commit comments

Comments
 (0)