From 8f35e6d8bd9980180909b2d3ebb5bda80aafbd2d Mon Sep 17 00:00:00 2001 From: Ricky Hanlon Date: Tue, 23 Apr 2024 10:21:15 -0400 Subject: [PATCH] Move RSC stuff to docs --- src/content/blog/2024/04/01/react-19.md | 492 +----------------- .../{react => full-stack}/directives.md | 10 +- src/content/reference/full-stack/index.md | 23 + .../reference/full-stack/server-actions.md | 214 ++++++++ .../reference/full-stack/server-components.md | 318 +++++++++++ .../{react => full-stack}/use-client.md | 0 .../{react => full-stack}/use-server.md | 0 src/sidebarReference.json | 69 ++- 8 files changed, 613 insertions(+), 513 deletions(-) rename src/content/reference/{react => full-stack}/directives.md (77%) create mode 100644 src/content/reference/full-stack/index.md create mode 100644 src/content/reference/full-stack/server-actions.md create mode 100644 src/content/reference/full-stack/server-components.md rename src/content/reference/{react => full-stack}/use-client.md (100%) rename src/content/reference/{react => full-stack}/use-server.md (100%) diff --git a/src/content/blog/2024/04/01/react-19.md b/src/content/blog/2024/04/01/react-19.md index d9c80a035..442f5cfcf 100644 --- a/src/content/blog/2024/04/01/react-19.md +++ b/src/content/blog/2024/04/01/react-19.md @@ -255,11 +255,11 @@ TODO: we can't yet -## React Server Components (RSC) {/*new-feature-server-components*/} +### React Server Components (RSC) {/*new-feature-server-components*/} -Server Components are a new option that allows rendering components ahead of time, before bundling, in an environment separate from your application (the "server"). They can run once at build time, or can be run for each request to a web server. +Server Components are a new option that allows rendering components ahead of time, before bundling, in an environment separate from your application (the "server"). They can run once at build time, or can be run for each request to a web server. -Today we're releasing React Server Components as semver stable in React 19. This means libraries that ship Server Components and Server Actions can target React 19 as a peer dependency for use in frameworks that support the [Full-stack React Architecture](/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision). +Today we're releasing React Server Components as semver stable in React 19. This means libraries that ship Server Components and Server Actions can target React 19 as a peer dependency for use in frameworks that support the [Full-stack React Architecture](/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision). @@ -277,303 +277,7 @@ TODO: -### Server Components without a Server {/*server-components-without-a-server*/} -Server components can run at build time to read from the filesystem or fetch static content, so a web server is not required. For example, you may want to read static data from a content management system. - -Without Server Components, it's common to fetch static data on the client with an Effect: -```js -// bundle.js -import marked from 'marked'; // 35.9K (11.2K gzipped) -import sanitizeHtml from 'sanitize-html'; // 206K (63.3K gzipped) - -function Page({page}) { - const [content, setContent] = useState(''); - // NOTE: loads *after* first page render. - useEffect(() => { - fetch(`/api/content/${page}`).then((data) => { - setContent(data.content); - }); - }, [page]); - - return
{sanitizeHtml(marked(content))}
; -} -``` -```js -// api.js -app.get(`/api/content/:page`, async (req, res) => { - const page = req.params.page; - const content = await file.readFile(`${page}.md`); - res.send({content}); -}); -``` - -This pattern means users need to download and parse an additional 75K (gzipped) of libraries, and wait for a second request to fetch the data after the page loads, just to render static content that will not change for the lifetime of the page. - -With Server Components, you can render these components once at build time: - -```js -import marked from 'marked'; // Not included in bundle -import sanitizeHtml from 'sanitize-html'; // Not included in bundle - -async function Page({page}) { - // NOTE: loads *during* render, when the app is built. - const content = await file.readFile(`${page}.md`); - - return
{sanitizeHtml(marked(content))}
; -} -``` - -The rendered output can then be server-side rendered (SSR) to HTML and uploaded to a CDN. When the app loads, the client will not see the original `Page` component, or the expensive libraries for rendering the markdown. The client will only see the rendered output: - -```js -
-``` - -This means the content is visible during first page load, and the bundle does not include the expensive libraries needed to render the static content. - - - -You may notice that the Server Component above is an async function: - -```js -async function Page({page}) { - //... -} -``` - -Async Components are a new feature of Server Components that allow you to `await` in render. - -See [Async components with Server Components](#async-components-with-server-components) below. - - - -### Server Components with a Server {/*server-components-with-a-server*/} -Server Components can also run on a web server during a request for a page, letting you access your data layer without having to build an API. They are rendered before your application is bundled, and can pass data and JSX as props to Client Components. - -Without Server Components, it's common to fetch dynamic data on the client in an Effect: - -```js -// bundle.js -function Note({id}) { - const [note, setNote] = useState(''); - // NOTE: loads *after* first render. - useEffect(() => { - fetch(`/api/notes/${id}`).then(data => { - setNote(data.note); - }); - }, [id]); - - return ( -
- -

{note}

-
- ); -} - -function Author({id}) { - const [author, setAuthor] = useState(''); - // NOTE: loads *after* Note renders. - // Causing an expensive client-server waterfall. - useEffect(() => { - fetch(`/api/authors/${id}`).then(data => { - setAuthor(data.author); - }); - }, [id]); - - return By: {author.name}; -} -``` -```js -// api -import db from './database'; - -app.get(`/api/notes/:id`, async (req, res) => { - const note = await db.notes.get(id); - res.send({note}); -}); - -app.get(`/api/authors/:id`, async (req, res) => { - const author = await db.authors.get(id); - res.send({author}); -}); -``` - -With Server Components, you can read the data and render it in the component: - -```js -import db from './database'; - -async function Note({id}) { - // NOTE: loads *during* render. - const note = await db.notes.get(id); - return ( -
- -

{note}

-
- ); -} - -async function Author({id}) { - // NOTE: loads *after* Node, - // but is fast if data is co-located. - const author = await db.authors.get(id); - return By: {author.name}; -} -``` - -The bundler then combines the data, rendered Server Components and dynamic Client Components into a bundle. Optionally, that bundle can then be server-side rendered (SSR) to create the initial HTML for the page. When the page loads, the browser does not see the original `Note` and `Author` components; only the rendered output is sent to the client: - -```js -
- By: The React Team -

React 19 Beta is...

-
-``` - -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. - - - -#### How do I make Server Components dynamic? {/*how-do-i-make-server-components-dynamic*/} - -TODO: use a router, re-fetch them. - - - -### Directives `"use client"` and `"use server"` {/*directives*/} - -[Directives](/reference/react/directives) are bundler features designed for full-stack React frameworks. They mark the “split points” between the two environments: - -- `"use client"` instructs the bundler to generate a `