I print this from my phone, so I apologize for the lack of formatting.
In my project, I am doing something similar to you; I have a static fetchData method, I loop through the components from renderProps and then call the static method and wait for promises to resolve.
Then I call the get function from my redux repository, string it and pass it to my render function on the server so that it can display the original state object on the client.
From the client, I just take this inital state variable and pass it to my redux store. Redux then processes the access to your client repository according to the one on the server. From there, you simply transfer your store to the supplier and continue as usual. You do not need to call your static method on the client at all.
As an example of what I said, you can check out my github project as the code explains itself. https://github.com/mr-antivirus/riur
Hope this helps!
[Edit] Here is the code!
Client.js
'use strict' import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import { Router, browserHistory } from 'react-router'; import createStore from '../shared/store/createStore'; import routes from '../shared/routes'; const store = createStore(window.__app_data); const history = browserHistory; render ( <Provider store={store}> <Router history={history} routes={routes} /> </Provider>, document.getElementById('content') )
Server.js
app.use((req, res, next) => { match({ routes, location:req.url }, (err, redirectLocation, renderProps) => { if (err) { return res.status(500).send(err); } if (redirectLocation) { return res.redirect(302, redirectLocation.pathname + redirectLocation.search); } if (!renderProps) { return next(); } // Create the redux store. const store = createStore(); // Retrieve the promises from React Router components that have a fetchData method. // We use this data to populate our store for server side rendering. const fetchedData = renderProps.components .filter(component => component.fetchData) .map(component => component.fetchData(store, renderProps.params)); // Wait until ALL promises are successful before rendering. Promise.all(fetchedData) .then(() => { const asset = { javascript: { main: '/js/bundle.js' } }; const appContent = renderToString( <Provider store={store}> <RouterContext {...renderProps} /> </Provider> ) const isProd = process.env.NODE_ENV !== 'production' ? false : true; res.send('<!doctype html>' + renderToStaticMarkup(<Html assets={asset} content={appContent} store={store} isProd={isProd} />)); }) .catch((err) => { // TODO: Perform better error logging. console.log(err); }); }); });
Redditcontainer.js
class Reddit extends Component {
HTML.js
'use strict'; import React, { Component, PropTypes } from 'react'; import ReactDom from 'react-dom'; import Helmet from 'react-helmet'; import serialize from 'serialize-javascript'; export default class Layout extends Component { static propTypes = { assets: PropTypes.object, content: PropTypes.string, store: PropTypes.object, isProd: PropTypes.bool } render () { const { assets, content, store, isProd } = this.props; const head = Helmet.rewind(); const attrs = head.htmlAttributes.toComponent(); return ( <html {...attrs}> <head> {head.base.toComponent()} {head.title.toComponent()} {head.meta.toComponent()} {head.link.toComponent()} {head.script.toComponent()} <link rel='shortcut icon' href='/favicon.ico' /> <meta name='viewport' content='width=device-width, initial-scale=1' /> </head> <body> <div id='content' dangerouslySetInnerHTML={{__html: content}} /> <script dangerouslySetInnerHTML={{__html: `window.__app_data=${serialize(store.getState())}; window.__isProduction=${isProd}`}} charSet='utf-8' /> <script src={assets.javascript.main} charSet='utf-8' /> </body> </html> ); } };
Repeat ...
- On the client, take the state variable and pass it to your store.
- On the server, scroll through your components by calling fetchData and passing your store. Wait for promises to resolve, then render.
- In HTML.js (your renderView function) serialize the Redux repository and render the output for the javascript variable for the client.
- In the React component, create a static fetchData method for the ONLY server to invoke. Submit the necessary actions.