From 1fa70eadf29a012dcca9c258a07adf887d1999a6 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Wed, 18 Jan 2017 17:58:00 +0200 Subject: [PATCH] Pass preloaded state to client side. --- public/index.html | 1 + server/index.js | 28 +++++++++++++++++++++------- src/app.js | 9 ++++++--- src/index.js | 6 +++++- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/public/index.html b/public/index.html index f7b8f2dc..e6fd9716 100644 --- a/public/index.html +++ b/public/index.html @@ -5,6 +5,7 @@ +
diff --git a/server/index.js b/server/index.js index 5b486f2a..b8e3aac8 100644 --- a/server/index.js +++ b/server/index.js @@ -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 = ` + + `; + + 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 // 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); } diff --git a/src/app.js b/src/app.js index 7e24a06f..6fe871dc 100644 --- a/src/app.js +++ b/src/app.js @@ -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 ( { @@ -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(); +export const renderApp = (url, serverContext, preloadedState) => { + const store = configureStore(preloadedState); + const body = ReactDOMServer.renderToString( + , + ); const head = Helmet.rewind(); return { head, body }; }; diff --git a/src/index.js b/src/index.js index d5c92c40..90e229be 100644 --- a/src/index.js +++ b/src/index.js @@ -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(, document.getElementById('root')); + const preloadedState = window.__PRELOADED_STATE__ || {}; // eslint-disable-line no-underscore-dangle + const store = configureStore(preloadedState); + + ReactDOM.render(, document.getElementById('root')); } // Export the function for server side rendering.