Skip to content

Commit

Permalink
Update Flight fixture to useFormState
Browse files Browse the repository at this point in the history
Updates the Flight fixture's Counter component to useFormState instead
of useState.
  • Loading branch information
acdlite committed Sep 13, 2023
1 parent 422ad8a commit 765ceb2
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 27 deletions.
6 changes: 5 additions & 1 deletion fixtures/flight/server/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,15 @@ app.all('/', async function (req, res, next) {
// For HTML, we're a "client" emulator that runs the client code,
// so we start by consuming the RSC payload. This needs a module
// map that reverse engineers the client-side path to the SSR path.
const root = await createFromNodeStream(rscResponse, moduleMap);
const {root, formState} = await createFromNodeStream(
rscResponse,
moduleMap
);
// Render it into HTML by resolving the client components
res.set('Content-type', 'text/html');
const {pipe} = renderToPipeableStream(root, {
bootstrapScripts: mainJSChunks,
experimental_formState: formState,
});
pipe(res);
} catch (e) {
Expand Down
15 changes: 9 additions & 6 deletions fixtures/flight/server/region.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const {readFile} = require('fs').promises;

const React = require('react');

async function renderApp(res, returnValue) {
async function renderApp(res, returnValue, formState) {
const {renderToPipeableStream} = await import(
'react-server-dom-webpack/server'
);
Expand Down Expand Up @@ -93,13 +93,13 @@ async function renderApp(res, returnValue) {
React.createElement(App),
];
// For client-invoked server actions we refresh the tree and return a return value.
const payload = returnValue ? {returnValue, root} : root;
const payload = {root, returnValue, formState};
const {pipe} = renderToPipeableStream(payload, moduleMap);
pipe(res);
}

app.get('/', async function (req, res) {
await renderApp(res, null);
await renderApp(res, null, null);
});

app.post('/', bodyParser.text(), async function (req, res) {
Expand All @@ -108,6 +108,7 @@ app.post('/', bodyParser.text(), async function (req, res) {
decodeReply,
decodeReplyFromBusboy,
decodeAction,
decodeFormState,
} = await import('react-server-dom-webpack/server');
const serverReference = req.get('rsc-action');
if (serverReference) {
Expand Down Expand Up @@ -139,7 +140,7 @@ app.post('/', bodyParser.text(), async function (req, res) {
// We handle the error on the client
}
// Refresh the client and return the value
renderApp(res, result);
renderApp(res, result, null);
} else {
// This is the progressive enhancement case
const UndiciRequest = require('undici').Request;
Expand All @@ -153,12 +154,14 @@ app.post('/', bodyParser.text(), async function (req, res) {
const action = await decodeAction(formData);
try {
// Wait for any mutations
await action();
const result = await action();
const formState = decodeFormState(result, formData);
renderApp(res, null, formState);
} catch (x) {
const {setServerState} = await import('../src/ServerState.js');
setServerState('Error: ' + x.message);
renderApp(res, null, null);
}
renderApp(res, null);
}
});

Expand Down
8 changes: 4 additions & 4 deletions fixtures/flight/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {Client} from './Client.js';

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

import {like, greet} from './actions.js';
import {like, greet, increment} from './actions.js';

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

Expand All @@ -32,9 +32,9 @@ export default async function App() {
<body>
<Container>
<h1>{getServerState()}</h1>
<Counter />
<Counter2 />
<Counter3 />
<Counter incrementAction={increment} />
<Counter2 incrementAction={increment} />
<Counter3 incrementAction={increment} />
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
Expand Down
9 changes: 6 additions & 3 deletions fixtures/flight/src/Counter.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
'use client';

import * as React from 'react';
import {experimental_useFormState as useFormState} from 'react-dom';

import Container from './Container.js';

export function Counter() {
const [count, setCount] = React.useState(0);
export function Counter({incrementAction}) {
const [count, incrementFormAction] = useFormState(incrementAction, 0);
return (
<Container>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<form>
<button formAction={incrementFormAction}>Count: {count}</button>
</form>
</Container>
);
}
4 changes: 4 additions & 0 deletions fixtures/flight/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ export async function greet(formData) {
}
return 'Hi ' + name + '!';
}

export async function increment(n) {
return n + 1;
}
38 changes: 25 additions & 13 deletions fixtures/flight/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,33 @@ async function callServer(id, args) {
return returnValue;
}

let data = createFromFetch(
fetch('/', {
headers: {
Accept: 'text/x-component',
},
}),
{
callServer,
}
);

function Shell({data}) {
const [root, setRoot] = useState(use(data));
const [root, setRoot] = useState(data);
updateRoot = setRoot;
return root;
}

ReactDOM.hydrateRoot(document, <Shell data={data} />);
async function hydrateApp() {
const {root, returnValue, formState} = await createFromFetch(
fetch('/', {
headers: {
Accept: 'text/x-component',
},
}),
{
callServer,
}
);

ReactDOM.hydrateRoot(document, <Shell data={root} />, {
// TODO: This part doesn't actually work because the server only returns
// form state during the request that submitted the form. Which means it
// the state needs to be transported as part of the HTML stream. We intend
// to add a feature to Fizz for this, but for now it's up to the
// metaframework to implement correctly.
experimental_formState: formState,
});
}

// Remove this line to simulate MPA behavior
hydrateApp();

0 comments on commit 765ceb2

Please sign in to comment.