I use the match method for server-side rendering, and the parameters in the callback are always undefined. You probably have something wrong, but it was a full day, and I canβt get around it.
Here is my server side rendering.
// Create location from the history module. let location = createLocation(req.url); match({Routes, location}, (error, redirectLocation, renderProps) => { // TODO : Verify why this is always undefined console.log('ERROR :: ', error) console.log('REDIRECT LOCATION :: ', redirectLocation) console.log('RENDER PROPS :: ', renderProps) if (redirectLocation) { res.redirect(redirectLocation.pathname + redirectLocation.search) } // TODO : Verify why this is breaking //else if (error || !renderProps) { // return console.log('Error while starting server :: ', error) //} else { Transmit.renderToString(RoutingContext, renderProps).then(({reactString, reactData}) => { console.log('REACT STRING :: ', reactString); console.log('REACT DATA :: ', reactData); let output = ( `<!doctype html> <html lang="en-us" style="min-height:100vh; width: 100%; background-color: #eee;"> <head> <meta charset="utf-8"> <title>react-isomorphic-pandora-app</title> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"> <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:400,100,700"> </head> <body> <div id="react-root">${reactString}</div> </body> </html>` ); var webserver = process.env.NODE_ENV === "production" ? "" : "//localhost:8080" output = Transmit.injectIntoMarkup(output, reactData, [`${webserver}/dist/client.js`]) res.send(output) }).catch((error) => { res.send(error.stack).type("text/plain").code(500) }) } })
Here is my client side.
import React from "react"; import ReactDOM from "react-dom"; import {Router} from "react-router"; import Transmit from "react-transmit"; import routes from "../views/Routes"; import {createHistory} from "history"; let reactRoot = window.document.getElementById("react-root"); let history = createHistory(); let location = history.createLocation(); const routerOption = { routes: routes, history: history, location: location } Transmit.render(Router, routerOption, reactRoot); if (process.env.NODE_ENV !== "production") { if (!reactRoot.firstChild || !reactRoot.firstChild.attributes || !reactRoot.firstChild.attributes["data-react-checksum"]) { console.error("Server-side React render was discarded. Make sure that your initial render does not contain any client-side code."); } }
Here are my routes.
import React from "react" import {Router, Route} from "react-router" import MenuView from "./Menu" import DefaultView from "./Default" import AnotherView from "./Another" export default ( <Router component={MenuView}> <Route path="/" component={DefaultView} /> <Route path="/another-view" component={AnotherView} /> </Router> );
Any help would be greatly appreciated. Thanks:)
EDIT --------
Here is the code inside my MenuView component.
class MenuView extends React.Component { constructor(){ super() this.menuItems = [ { type: MenuItem.Types.SUBHEADER, text: 'Menu sub header' }, { route: '/', text: 'Home' }, { route: '/another-view', text: 'Another view' } ] } childContextTypes = { muiTheme: React.PropTypes.object }; getChildContext() { return { muiTheme: ThemeManager.getMuiTheme(DefaultTheme) } } _getSelectedIndex = () => { let currentItem; for (let i = this.menuItems.length - 1; i >= 0; i--) { currentItem = this.menuItems[i]; if (currentItem.route && this.props.history.isActive(currentItem.route)) return i; } } _onLeftNavChange = (e, key, payload) => { this.props.history.pushState(null, payload.route); } render () { var style = { paddingTop: '92px' } return ( <div> <LeftNav ref="leftNav" menuItems={this.menuItems} onChange={this._onLeftNavChange} selectedIndex={this._getSelectedIndex()} style={style}/> <section className="content"> {this.props.children} </section> </div> ) } }