Context As Undefined When Using React Router 4 For Server Side Rendering

I'm working on implementing server-side rendering with React Router 4 at a basic level to understand how it works. However, I am facing several problems and it is not clear in the React Router documentation how to solve them:

1) My context variable at / server / routes is undefined.

I've seen in previous tutorials that React Router used createServerRenderContext (); however, their documentation is not mentioned anymore, so I assume they got rid of it. I thought the StaticRouter should create your context for you when it renders? How can I define my context?

2) My html variable which renders the StaticRouter as a string shows these two errors in the console:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it defined in.

Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it defined in.

      

I don't quite understand why this is a problem. I believe this is exported correctly and I am passing this through renderToString. Why is this giving me an error?

Any help is greatly appreciated! Here's my code below:

Server side

/server/server.js

import express from 'express'
import router from './routes/index.js'

const app = express();

app.use(express.static('public'));
app.use(router)

const PORT = 3000;
app.listen(PORT, function(){
  console.log('Listening on ' + PORT)
});

      

/server/routes/index.js

import { Router } from 'express'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { StaticRouter } from 'react-router'
import App from '../../client/App'

const router = Router();

router.get('*', function(request, response) {

  const context = {}

  const html = ReactDOMServer.renderToString(
    <StaticRouter location={request.url} context={context}>
      <App/>
    </StaticRouter>
  );

  if (context.url) {
    response.writeHead(301, {
      Location: context.url
    })
    response.end()
  } else {
    response.write(html)
    response.end()
  }
});

export default router

      

Client side

/client/index.js

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router';

import App from './App'

const props = window.PROPS;

ReactDOM.render(
  <BrowserRouter>
    <App {...props} />
  </BrowserRouter>,
  document
);

      

/client/App.js

import React from 'react'

class App extends React.Component {
  constructor() {
      super()
  }
  handleClick() {
    alert()
  }
  render() {
    return (
      <html>
        <head>
          <title>{this.props.title}</title>
          <link rel="stylesheet" href="/style.css" />
        </head>
        <body>
          <main>
            <h1>{this.props.title}</h1>
            <p>This is some text that makes up a paragraph</p>
            <button onClick={this.handleClick}>Click me</button>
          </main>
          <script dangerouslySetInnerHTML={{
            __html: 'window.PROPS=' + JSON.stringify(this.props)
          }} />
          <script src="/bundle.js" />
        </body>
      </html>
    )
  }
}

export default App;

      

Webpack.config.js

var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: './src/client/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'public'),
    publicPath: '/public/'
  },
  module: {
    rules: [
      {
        test: /\.js?$/,
        exclude: /node_modules/,
        include: path.join(__dirname, 'src'),
        use: [
          {
            loader: 'babel-loader',
            query: {
              presets: ['react', ['es2015', { 'modules': false }], 'stage-0'],
              plugins: ['react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy']
            }
          }
        ]
      }
    ]
  }
};

      

+3
javascript node.js reactjs react-router single-page-application


source to share


No one has answered this question yet

Check out similar questions:

1203
Navigate programmatically with responsive router
501
React router urls not working when updated or manually written
89
Client routing (using responder adapter) and server side routing
87
How to allow webpack-dev-server to resolve entry points from react router
thirty
Server-side dispatch using react, react-router and expression
2
How to set up server side rendering with Reactive Router 2
2
ES6 Server Side React how to import React component?
0
React Router Switch not passing specific component
0
Server side data collection using a relay
-1
Reagent router and one-way



All Articles
Loading...
X
Show
Funny
Dev
Pics