/
githubmr
/
facebook-react
Обзор
Документация
Войти
/
githubmr
/
facebook-react
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
fixtures/flight/src/App.js
247 строк
6 KB
Sebastian Markbåge
[Flight] Track I/O Entry for the RSC Stream itself (#34425)
09 сен 2025, 23:46
Не верифицирован
09 сен 2025, 23:46
969a979
Код
Авторство
О чём код?
import * as React from 'react'; import {renderToReadableStream} from 'react-server-dom-webpack/server'; import {createFromReadableStream} from 'react-server-dom-webpack/client'; import {PassThrough, Readable} from 'stream'; import Container from './Container.js'; import {Counter} from './Counter.js'; import {Counter as Counter2} from './Counter2.js'; import AsyncModule from './cjs/Counter3.js'; const Counter3 = await(AsyncModule); import ShowMore from './ShowMore.js'; import Button from './Button.js'; import Form from './Form.js'; import {Dynamic} from './Dynamic.js'; import {Client} from './Client.js'; import {Navigate} from './Navigate.js'; import {Note} from './cjs/Note.js'; import {GenerateImage} from './GenerateImage.js'; import LargeContent from './LargeContent.js'; import {like, greet, increment} from './actions.js'; import {getServerState} from './ServerState.js'; import {sdkMethod} from './library.js'; const promisedText = new Promise(resolve => setTimeout(() => resolve('deferred text'), 50) ); function Foo({children}) { return <div>{children}</div>; } async function delayedError(text, ms) { return new Promise((_, reject) => setTimeout(() => reject(new Error(text)), ms) ); } async function delay(text, ms) { return new Promise(resolve => setTimeout(() => resolve(text), ms)); } async function delayTwice() { try { await delayedError('Delayed exception', 20); } catch (x) { // Ignored } await delay('', 10); } async function delayTrice() { const p = delayTwice(); await delay('', 40); return p; } async function Bar({children}) { await delayTrice(); return <div>{children}</div>; } async function ThirdPartyComponent() { return await delay('hello from a 3rd party', 30); } let cachedThirdPartyStream; // We create the Component outside of AsyncLocalStorage so that it has no owner. // That way it gets the owner from the call to createFromNodeStream. const thirdPartyComponent = <ThirdPartyComponent />; function simulateFetch(cb, latencyMs) { return new Promise(resolve => { // Request latency setTimeout(() => { const result = cb(); // Response latency setTimeout(() => { resolve(result); }, latencyMs); }, latencyMs); }); } async function fetchThirdParty(noCache) { // We're using the Web Streams APIs for tee'ing convenience. let stream; if (cachedThirdPartyStream && !noCache) { stream = cachedThirdPartyStream; } else { stream = await simulateFetch( () => renderToReadableStream( thirdPartyComponent, {}, {environmentName: 'third-party'} ), 25 ); } const [stream1, stream2] = stream.tee(); cachedThirdPartyStream = stream1; return createFromReadableStream(stream2, { serverConsumerManifest: { moduleMap: {}, serverModuleMap: null, moduleLoading: null, }, }); } async function ServerComponent({noCache}) { await delay('deferred text', 50); return await fetchThirdParty(noCache); } let veryDeepObject = [ { bar: { baz: { a: {}, }, }, }, { bar: { baz: { a: {}, }, }, }, { bar: { baz: { a: {}, }, }, }, { bar: { baz: { a: { b: { c: { d: { e: { f: { g: { h: { i: { j: { k: { l: { m: { yay: 'You reached the end', }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, ]; export default async function App({prerender, noCache}) { const res = await fetch('http://localhost:3001/todos'); const todos = await res.json(); await sdkMethod('http://localhost:3001/todos'); console.log('Expand me:', veryDeepObject); const dedupedChild = <ServerComponent noCache={noCache} />; const message = getServerState(); return ( <html lang="en"> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Flight</title> </head> <body> <Container> {prerender ? ( <meta data-testid="prerendered" name="prerendered" content="true" /> ) : ( <meta content="when not prerendering we render this meta tag. When prerendering you will expect to see this tag and the one with data-testid=prerendered because we SSR one and hydrate the other" /> )} <h1>{message}</h1> <React.Suspense fallback={null}> <div data-testid="promise-as-a-child-test"> Promise as a child hydrates without errors: {promisedText} </div> </React.Suspense> <Counter incrementAction={increment} /> <Counter2 incrementAction={increment} /> <Counter3 incrementAction={increment} /> <ul> {todos.map(todo => ( <li key={todo.id}>{todo.text}</li> ))} </ul> <ShowMore> <p>Lorem ipsum</p> </ShowMore> <Form action={greet} /> <div> <Button action={like}>Like</Button> </div> <div> loaded statically: <Dynamic /> </div> <div> <GenerateImage message={message} /> </div> <Client /> <Note /> <Foo>{dedupedChild}</Foo> <Bar>{Promise.resolve([dedupedChild])}</Bar> <Navigate /> {prerender ? null : ( // TODO: prerender is broken for large content for some reason. <React.Suspense fallback={null}> <LargeContent /> </React.Suspense> )} </Container> </body> </html> ); }