Skip to content

Commit 4152ed3

Browse files
committed
Update Flight fixture to useFormState
Updates the Flight fixture's Counter component to useFormState instead of useState.
1 parent 0d7c8a5 commit 4152ed3

File tree

6 files changed

+48
-27
lines changed

6 files changed

+48
-27
lines changed

fixtures/flight/server/global.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,15 @@ app.all('/', async function (req, res, next) {
138138
// For HTML, we're a "client" emulator that runs the client code,
139139
// so we start by consuming the RSC payload. This needs a module
140140
// map that reverse engineers the client-side path to the SSR path.
141-
const root = await createFromNodeStream(rscResponse, moduleMap);
141+
const {root, formState} = await createFromNodeStream(
142+
rscResponse,
143+
moduleMap
144+
);
142145
// Render it into HTML by resolving the client components
143146
res.set('Content-type', 'text/html');
144147
const {pipe} = renderToPipeableStream(root, {
145148
bootstrapScripts: mainJSChunks,
149+
experimental_formState: formState,
146150
});
147151
pipe(res);
148152
} catch (e) {

fixtures/flight/server/region.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const {readFile} = require('fs').promises;
4646

4747
const React = require('react');
4848

49-
async function renderApp(res, returnValue) {
49+
async function renderApp(res, returnValue, formState) {
5050
const {renderToPipeableStream} = await import(
5151
'react-server-dom-webpack/server'
5252
);
@@ -93,13 +93,13 @@ async function renderApp(res, returnValue) {
9393
React.createElement(App),
9494
];
9595
// For client-invoked server actions we refresh the tree and return a return value.
96-
const payload = returnValue ? {returnValue, root} : root;
96+
const payload = {root, returnValue, formState};
9797
const {pipe} = renderToPipeableStream(payload, moduleMap);
9898
pipe(res);
9999
}
100100

101101
app.get('/', async function (req, res) {
102-
await renderApp(res, null);
102+
await renderApp(res, null, null);
103103
});
104104

105105
app.post('/', bodyParser.text(), async function (req, res) {
@@ -108,6 +108,7 @@ app.post('/', bodyParser.text(), async function (req, res) {
108108
decodeReply,
109109
decodeReplyFromBusboy,
110110
decodeAction,
111+
decodeFormState,
111112
} = await import('react-server-dom-webpack/server');
112113
const serverReference = req.get('rsc-action');
113114
if (serverReference) {
@@ -139,7 +140,7 @@ app.post('/', bodyParser.text(), async function (req, res) {
139140
// We handle the error on the client
140141
}
141142
// Refresh the client and return the value
142-
renderApp(res, result);
143+
renderApp(res, result, null);
143144
} else {
144145
// This is the progressive enhancement case
145146
const UndiciRequest = require('undici').Request;
@@ -153,12 +154,14 @@ app.post('/', bodyParser.text(), async function (req, res) {
153154
const action = await decodeAction(formData);
154155
try {
155156
// Wait for any mutations
156-
await action();
157+
const result = await action();
158+
const formState = decodeFormState(result, formData);
159+
renderApp(res, null, formState);
157160
} catch (x) {
158161
const {setServerState} = await import('../src/ServerState.js');
159162
setServerState('Error: ' + x.message);
163+
renderApp(res, null, null);
160164
}
161-
renderApp(res, null);
162165
}
163166
});
164167

fixtures/flight/src/App.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {Client} from './Client.js';
1515

1616
import {Note} from './cjs/Note.js';
1717

18-
import {like, greet} from './actions.js';
18+
import {like, greet, increment} from './actions.js';
1919

2020
import {getServerState} from './ServerState.js';
2121

@@ -32,9 +32,9 @@ export default async function App() {
3232
<body>
3333
<Container>
3434
<h1>{getServerState()}</h1>
35-
<Counter />
36-
<Counter2 />
37-
<Counter3 />
35+
<Counter incrementAction={increment} />
36+
<Counter2 incrementAction={increment} />
37+
<Counter3 incrementAction={increment} />
3838
<ul>
3939
{todos.map(todo => (
4040
<li key={todo.id}>{todo.text}</li>

fixtures/flight/src/Counter.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
'use client';
22

33
import * as React from 'react';
4+
import {experimental_useFormState as useFormState} from 'react-dom';
45

56
import Container from './Container.js';
67

7-
export function Counter() {
8-
const [count, setCount] = React.useState(0);
8+
export function Counter({incrementAction}) {
9+
const [count, incrementFormAction] = useFormState(incrementAction, 0);
910
return (
1011
<Container>
11-
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
12+
<form>
13+
<button formAction={incrementFormAction}>Count: {count}</button>
14+
</form>
1215
</Container>
1316
);
1417
}

fixtures/flight/src/actions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ export async function greet(formData) {
1818
}
1919
return 'Hi ' + name + '!';
2020
}
21+
22+
export async function increment(n) {
23+
return n + 1;
24+
}

fixtures/flight/src/index.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,28 @@ async function callServer(id, args) {
2424
return returnValue;
2525
}
2626

27-
let data = createFromFetch(
28-
fetch('/', {
29-
headers: {
30-
Accept: 'text/x-component',
31-
},
32-
}),
33-
{
34-
callServer,
35-
}
36-
);
37-
3827
function Shell({data}) {
39-
const [root, setRoot] = useState(use(data));
28+
const [root, setRoot] = useState(data);
4029
updateRoot = setRoot;
4130
return root;
4231
}
4332

44-
ReactDOM.hydrateRoot(document, <Shell data={data} />);
33+
async function hydrateApp() {
34+
const {root, returnValue, formState} = await createFromFetch(
35+
fetch('/', {
36+
headers: {
37+
Accept: 'text/x-component',
38+
},
39+
}),
40+
{
41+
callServer,
42+
}
43+
);
44+
45+
ReactDOM.hydrateRoot(document, <Shell data={root} />, {
46+
experimental_formState: formState,
47+
});
48+
}
49+
50+
// Remove this line to simulate MPA behavior
51+
hydrateApp();

0 commit comments

Comments
 (0)