mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
Pass preloaded state to client side.
This commit is contained in:
parent
731db1991d
commit
1fa70eadf2
4 changed files with 33 additions and 11 deletions
|
|
@ -5,6 +5,7 @@
|
|||
<!--!title-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<!--!preloadedStateScript-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"><!--!body--></div>
|
||||
|
|
|
|||
|
|
@ -21,12 +21,13 @@ const helmet = require('helmet');
|
|||
const compression = require('compression');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const auth = require('./auth');
|
||||
const qs = require('qs');
|
||||
const _ = require('lodash');
|
||||
const React = require('react');
|
||||
const { createServerRenderContext } = require('react-router');
|
||||
const auth = require('./auth');
|
||||
|
||||
// Construct the bundle path where the server side renering function
|
||||
// Construct the bundle path where the server side rendering function
|
||||
// can be imported.
|
||||
const buildPath = path.resolve(__dirname, '..', 'build');
|
||||
const manifestPath = path.join(buildPath, 'asset-manifest.json');
|
||||
|
|
@ -65,9 +66,17 @@ const template = _.template(indexHtml, {
|
|||
escape: reNoMatch,
|
||||
});
|
||||
|
||||
function render(url, context) {
|
||||
const { head, body } = renderApp(url, context);
|
||||
return template({ title: head.title.toString(), body });
|
||||
function render(url, context, preloadedState) {
|
||||
const { head, body } = renderApp(url, context, preloadedState);
|
||||
|
||||
// Preloaded state needs to be passed for client side too.
|
||||
const preloadedStateScript = `
|
||||
<script>
|
||||
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\x3c')};
|
||||
</script>
|
||||
`;
|
||||
|
||||
return template({ title: head.title.toString(), preloadedStateScript, body });
|
||||
}
|
||||
|
||||
const env = process.env.NODE_ENV;
|
||||
|
|
@ -91,7 +100,12 @@ app.use('/static', express.static(path.join(buildPath, 'static')));
|
|||
|
||||
app.get('*', (req, res) => {
|
||||
const context = createServerRenderContext();
|
||||
const html = render(req.url, context);
|
||||
const filters = qs.parse(req.query);
|
||||
|
||||
// TODO fetch this asynchronously
|
||||
const preloadedState = { search: { filters } };
|
||||
|
||||
const html = render(req.url, context, preloadedState);
|
||||
const result = context.getResult();
|
||||
|
||||
if (result.redirect) {
|
||||
|
|
@ -100,7 +114,7 @@ app.get('*', (req, res) => {
|
|||
// Do a second render pass with the context to clue <Miss>
|
||||
// components into rendering this time.
|
||||
// See: https://react-router.now.sh/ServerRouter
|
||||
res.status(404).send(render(req.url, context));
|
||||
res.status(404).send(render(req.url, context, preloadedState));
|
||||
} else {
|
||||
res.send(html);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const { any, string } = PropTypes;
|
|||
ClientApp.propTypes = { store: any.isRequired };
|
||||
|
||||
export const ServerApp = props => {
|
||||
const { url, context } = props;
|
||||
const { url, context, store } = props;
|
||||
return (
|
||||
<ServerRouter location={url} context={context}>
|
||||
{
|
||||
|
|
@ -52,8 +52,11 @@ ServerApp.propTypes = { url: string.isRequired, context: any.isRequired, store:
|
|||
* - {String} body: Rendered application body of the given route
|
||||
* - {Object} head: Application head metadata from react-helmet
|
||||
*/
|
||||
export const renderApp = (url, serverContext) => {
|
||||
const body = ReactDOMServer.renderToString(<ServerApp url={url} context={serverContext} />);
|
||||
export const renderApp = (url, serverContext, preloadedState) => {
|
||||
const store = configureStore(preloadedState);
|
||||
const body = ReactDOMServer.renderToString(
|
||||
<ServerApp url={url} context={serverContext} store={store} />,
|
||||
);
|
||||
const head = Helmet.rewind();
|
||||
return { head, body };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,12 +14,16 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { ClientApp, renderApp } from './app';
|
||||
import configureStore from './store';
|
||||
|
||||
import './index.css';
|
||||
|
||||
// If we're in a browser already, render the client application.
|
||||
if (typeof window !== 'undefined') {
|
||||
ReactDOM.render(<ClientApp />, document.getElementById('root'));
|
||||
const preloadedState = window.__PRELOADED_STATE__ || {}; // eslint-disable-line no-underscore-dangle
|
||||
const store = configureStore(preloadedState);
|
||||
|
||||
ReactDOM.render(<ClientApp store={store} />, document.getElementById('root'));
|
||||
}
|
||||
|
||||
// Export the function for server side rendering.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue