Skip to content

Commit 5498014

Browse files
committed
server functions now
Also improve test reliability
1 parent 3e40ff7 commit 5498014

File tree

10 files changed

+57
-21
lines changed

10 files changed

+57
-21
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<div>
2-
<h1 align="center"><a href="https://www.epicweb.dev/workshops">React Server Components and Actions</a></h1>
2+
<h1 align="center"><a href="https://www.epicweb.dev/workshops">React Server Components and Functions</a></h1>
33
<strong>
4-
Understand React Server Components and Server Actions by building a framework with them.
4+
Understand React Server Components and Server Functions by building a framework with them.
55
</strong>
66
<p>
7-
In this workshop we'll be building a framework built on React Server Components and Server Actions from scratch. No build tools. No TypeScript, no Vite, no JSX. Just the Browser, Node.js, and React. This is how you develop a <strong>deep</strong> understanding of something. Let's go!
7+
In this workshop we'll be building a framework built on React Server Components and Server Functions from scratch. No build tools. No TypeScript, no Vite, no JSX. Just the Browser, Node.js, and React. This is how you develop a <strong>deep</strong> understanding of something. Let's go!
88
</p>
99
</div>
1010

exercises/02.server-components/README.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Let's compare initial render of a SPA that uses JSON with a SPA that uses RSCs:
4242

4343
</details>
4444

45-
![A flowchart for React Server Components and actions as described below](/images/super-simple-rsc-initial-render.png)
45+
![A flowchart for React Server Components and Functions as described below](/images/super-simple-rsc-initial-render.png)
4646

4747
<details>
4848
<summary>Here's a bullet-point text version of the flowchart:</summary>

exercises/04.router/02.problem.pending-ui/tests/pending-ui.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ test('should display pending UI when performing a search and selecting a ship',
1515

1616
// simulate a slow network for the /rsc endpoint so we force the pending UI to show up
1717
await page.route('/rsc/*', async route => {
18-
await new Promise(resolve => setTimeout(resolve, 400))
18+
await new Promise(resolve =>
19+
setTimeout(resolve, process.env.CI ? 1000 : 400),
20+
)
1921
await route.continue()
2022
})
2123

exercises/04.router/02.solution.pending-ui/tests/pending-ui.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ test('should display pending UI when performing a search and selecting a ship',
1515

1616
// simulate a slow network for the /rsc endpoint so we force the pending UI to show up
1717
await page.route('/rsc/*', async route => {
18-
await new Promise(resolve => setTimeout(resolve, 400))
18+
await new Promise(resolve =>
19+
setTimeout(resolve, process.env.CI ? 1000 : 400),
20+
)
1921
await route.continue()
2022
})
2123

exercises/04.router/05.problem.cache/tests/cache.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ test('going forward and backward in history updates the UI', async ({
99

1010
// simulate a slow network for the /rsc endpoint so we force the pending UI to show up
1111
await page.route('/rsc/*', async route => {
12-
await new Promise(resolve => setTimeout(resolve, 400))
12+
await new Promise(resolve =>
13+
setTimeout(resolve, process.env.CI ? 1000 : 400),
14+
)
1315
await route.continue()
1416
})
1517

exercises/04.router/05.solution.cache/tests/cache.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ test('going forward and backward in history updates the UI', async ({
99

1010
// simulate a slow network for the /rsc endpoint so we force the pending UI to show up
1111
await page.route('/rsc/*', async route => {
12-
await new Promise(resolve => setTimeout(resolve, 400))
12+
await new Promise(resolve =>
13+
setTimeout(resolve, process.env.CI ? 1000 : 400),
14+
)
1315
await route.continue()
1416
})
1517

exercises/05.actions/README.mdx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,26 @@ submission is often a challenge (and it's different in every app).
1717
In React's quest to "compose all the things," React has a solution to this
1818
problem in the form of "server actions."
1919

20-
Server actions are similar to client components in many ways. The RSC payload
21-
carries with it a reference to the action you wish to perform and when the form
22-
is submitted, the server gets that reference so it knows the right function to
23-
call.
24-
25-
In practice, what this means is you get to pass a server-only function to a
20+
Server actions are a subset of server functions. Server functions are similar to
21+
client components in many ways. The RSC payload carries with it a reference to
22+
the function you wish to perform and when the form is submitted, the server gets
23+
that reference so it knows the right function to call.
24+
25+
To expose these server functions to be called from the client, you use the
26+
`'use server'` directive. Rather than rewriting the module to not contain the
27+
function, the `'use server'` directive adds reference information so the RSC
28+
payload generation can work.
29+
30+
When that function is called, it can be wrapped inside a `startTransition`
31+
which gives you a pending state for while that server function runs and that
32+
transition is pending.
33+
34+
To take it a step further, `useActionState` turns that server function into an
35+
action which resembles the way native form actions without the URL indirection.
36+
This approach even support progressive enhancement such that if the JavaScript
37+
has not yet been loaded, the form will act like a normal form submission.
38+
39+
In practice, what this all means is you get to pass a server-only function to a
2640
client component and that component can call the function when it needs to.
2741

2842
Here's an example of this:
@@ -113,3 +127,10 @@ use on the client as needed.
113127
📜 Relevant Docs:
114128

115129
- [`use-server`](https://react.dev/reference/react/use-server)
130+
- [Server Functions](https://19.react.dev/reference/rsc/server-functions)
131+
132+
<callout-warning>
133+
Originally, there was a single concept called "server actions" but later this
134+
was split into two concepts: "server actions" and "server functions". Server
135+
actions are a subset of server functions, specifically for form submissions.
136+
</callout-warning>

exercises/FINISHED.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
Hooray! You're all done! 👏👏
66

77
[Welcome to the ranks](https://twitter.com/kentcdodds/status/1773047467413495876)
8-
of those of us who have implemented a React Server Components and Actions
8+
of those of us who have implemented a React Server Components and Functions
99
framework! 🎉

exercises/README.mdx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
oriented and to give you your assignments for the workshop!
77

88
Today we're going to implement a React framework based on React Server
9-
Components and Actions! When we're finished with this, you'll have a deep
10-
understanding of the primitives that power React Server Components and Actions
9+
Components and Functions! When we're finished with this, you'll have a deep
10+
understanding of the primitives that power React Server Components and Functions
1111
which is the future of React.
1212

1313
<callout-danger>
@@ -30,8 +30,8 @@ on under the hood.
3030

3131
<callout-danger>
3232
One of the challenges you're going to have to face is understanding the
33-
difference between the requirements of React Server Components and Actions vs
34-
our own choices in this specific implementation of RSCs. RSCs are a very
33+
difference between the requirements of React Server Components and Functions
34+
vs our own choices in this specific implementation of RSCs. RSCs are a very
3535
low-level primitive and there are lots of ways to accomplish the same thing.
3636
Different implementations will have different trade-offs. Try to focus on the
3737
overall concepts and not get too bogged down in the specifics of this
@@ -90,7 +90,7 @@ of requesting data from the server and then rendering it on the client, you can
9090
make a request, have React generate the UI on the server, and send it back to
9191
the client.
9292

93-
![A flowchart for React Server Components and actions as described below](/images/super-simple-rsc.png)
93+
![A flowchart for React Server Components and Functions as described below](/images/super-simple-rsc.png)
9494

9595
<details>
9696
<summary>Here's a bullet-point text version of the flowchart:</summary>
@@ -141,3 +141,10 @@ SPAs or even server-rendered apps.
141141
</callout-info>
142142

143143
Let's go!
144+
145+
🎵 Check out the workshop theme song! 🎶
146+
147+
<VideoEmbed
148+
title="Epic React: React Server Components Theme Song"
149+
url="https://www.youtube.com/embed/mYX65QSSxYE"
150+
/>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"epicshop": {
55
"title": "React Server Components 🤹",
66
"githubRoot": "https://github.com/epicweb-dev/react-server-components/blob/main",
7-
"subtitle": "Understand React Server Components and Server Actions by building a framework with them.",
7+
"subtitle": "Understand React Server Components and Server Functions by building a framework with them.",
88
"product": {
99
"host": "www.epicreact.dev",
1010
"slug": "react-server-components",

0 commit comments

Comments
 (0)