Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 765ceb2

Browse files
committed
Update Flight fixture to useFormState
Updates the Flight fixture's Counter component to useFormState instead of useState.
1 parent 422ad8a commit 765ceb2

File tree

6 files changed

+53
-27
lines changed

6 files changed

+53
-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: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,33 @@ 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+
// TODO: This part doesn't actually work because the server only returns
47+
// form state during the request that submitted the form. Which means it
48+
// the state needs to be transported as part of the HTML stream. We intend
49+
// to add a feature to Fizz for this, but for now it's up to the
50+
// metaframework to implement correctly.
51+
experimental_formState: formState,
52+
});
53+
}
54+
55+
// Remove this line to simulate MPA behavior
56+
hydrateApp();

0 commit comments

Comments
 (0)