Skip to content

Commit

Permalink
[Fizz] Wire up the Fixture (facebook#21273)
Browse files Browse the repository at this point in the history
* Wire up fizz to fixture

* Fixed typo conditional
  • Loading branch information
sebmarkbage committed Apr 22, 2021
1 parent e8cdce4 commit af5037a
Show file tree
Hide file tree
Showing 8 changed files with 3,184 additions and 1,412 deletions.
4 changes: 2 additions & 2 deletions fixtures/ssr/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ if (process.env.NODE_ENV === 'development') {
delete require.cache[key];
}
const render = require('./render').default;
res.send(render(req.url));
render(req.url, res);
});
} else {
const render = require('./render').default;
app.get('/', function(req, res) {
res.send(render(req.url));
render(req.url, res);
});
}

Expand Down
34 changes: 28 additions & 6 deletions fixtures/ssr/server/render.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {renderToString} from 'react-dom/server';
import {pipeToNodeWritable} from 'react-dom/unstable-fizz';

import App from '../src/components/App';

Expand All @@ -14,9 +14,31 @@ if (process.env.NODE_ENV === 'development') {
assets = require('../build/asset-manifest.json');
}

export default function render() {
var html = renderToString(<App assets={assets} />);
// There's no way to render a doctype in React so prepend manually.
// Also append a bootstrap script tag.
return '<!DOCTYPE html>' + html;
export default function render(url, res) {
res.socket.on('error', error => {
// Log fatal errors
console.error('Fatal', error);
});
let didError = false;
const {startWriting, abort} = pipeToNodeWritable(
<App assets={assets} />,
res,
{
onReadyToStream() {
// If something errored before we started streaming, we set the error code appropriately.
res.statusCode = didError ? 500 : 200;
res.setHeader('Content-type', 'text/html');
// There's no way to render a doctype in React so prepend manually.
res.write('<!DOCTYPE html>');
startWriting();
},
onError(x) {
didError = true;
console.error(x);
},
}
);
// Abandon and switch to client rendering after 5 seconds.
// Try lowering this to see the client recover.
setTimeout(abort, 5000);
}
34 changes: 20 additions & 14 deletions fixtures/ssr/src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,29 @@ function LoadingIndicator() {
return <div className={theme + '-loading'}>Loading...</div>;
}

export default function App({assets}) {
function Content() {
let [CurrentPage, switchPage] = useState(() => Page);
return (
<div>
<h1>Hello World</h1>
<a className="link" onClick={() => switchPage(() => Page)}>
Page 1
</a>
{' | '}
<a className="link" onClick={() => switchPage(() => Page2)}>
Page 2
</a>
<Suspense fallback={<LoadingIndicator />}>
<CurrentPage />
</Suspense>
</div>
);
}

export default function App({assets}) {
return (
<Chrome title="Hello World" assets={assets}>
<div>
<h1>Hello World</h1>
<a className="link" onClick={() => switchPage(() => Page)}>
Page 1
</a>
{' | '}
<a className="link" onClick={() => switchPage(() => Page2)}>
Page 2
</a>
<Suspense fallback={<LoadingIndicator />}>
<CurrentPage />
</Suspense>
</div>
<Content />
</Chrome>
);
}
32 changes: 19 additions & 13 deletions fixtures/ssr/src/components/Chrome.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import React, {Component} from 'react';
import React, {
Component,
Suspense,
unstable_startTransition as startTransition,
} from 'react';

import Theme, {ThemeToggleButton} from './Theme';

Expand All @@ -23,18 +27,20 @@ export default class Chrome extends Component {
__html: `<b>Enable JavaScript to run this app.</b>`,
}}
/>
<Theme.Provider value={this.state.theme}>
{this.props.children}
<div>
<ThemeToggleButton
onChange={theme => {
React.startTransition(() => {
this.setState({theme});
});
}}
/>
</div>
</Theme.Provider>
<Suspense fallback="Loading...">
<Theme.Provider value={this.state.theme}>
{this.props.children}
<div>
<ThemeToggleButton
onChange={theme => {
startTransition(() => {
this.setState({theme});
});
}}
/>
</div>
</Theme.Provider>
</Suspense>
<script
dangerouslySetInnerHTML={{
__html: `assetManifest = ${JSON.stringify(assets)};`,
Expand Down
19 changes: 10 additions & 9 deletions fixtures/ssr/src/components/Suspend.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ let isResolved = false;
export default function Suspend({children}) {
// This will suspend the content from rendering but only on the client.
// This is used to demo a slow loading app.
if (typeof window === 'object') {
if (!isResolved) {
if (promise === null) {
promise = new Promise(resolve => {
setTimeout(() => {
if (!isResolved) {
if (promise === null) {
promise = new Promise(resolve => {
setTimeout(
() => {
isResolved = true;
resolve();
}, 6000);
});
}
throw promise;
},
typeof window === 'object' ? 6000 : 1000
);
});
}
throw promise;
}
return children;
}
2 changes: 1 addition & 1 deletion fixtures/ssr/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {createRoot} from 'react-dom';
import {unstable_createRoot as createRoot} from 'react-dom';

import App from './components/App';

Expand Down
Loading

0 comments on commit af5037a

Please sign in to comment.