3
votes

I'm unable to get the URL parameter feature in React Router to work, any insight would be helpful! I tried using the 'react-router-dom' instead of 'react-router' but I get the errors this guy is getting: https://github.com/ReactTraining/react-router/issues/1799

When I do localhost:8000, the app works. When I go to localhost:8000/123, the browser renders the index.html as is with no react. Is Express interfering with React? In Express all i have is the following:

app.get('*', function response(req, res) {
  res.write(middleware.fileSystem.readFileSync(path.join(__dirname, 'dist/index.html')));
  res.end();
});

Here's my main.js:

import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, browserHistory } from 'react-router';
import Routes from './shared/components/Routes';
const ROOT_ELEMENT = 'app';
ReactDOM.render((
   <Router history={browserHistory}>
   {Routes}
   </Router>
), document.getElementById(ROOT_ELEMENT));

My routes.js:

import { Route, IndexRoute, Link } from 'react-router';

import App from './App';
import HomePage from '../../pages/home/page';
import AboutPage from '../../pages/about/page';

const Child = ({ match }) => (
  <div>
    <h3>ID: {match.params.id}</h3>
  </div>
)

export default (
  <Route path="/" component={App}>
    <IndexRoute component={HomePage} />
    {/* <Route path="about" component={AboutPage} /> */}
    <Route path="/:id" component={Child} />
  </Route>
);

My Home component is defined like this in a different file (left out all the imports and lifecycle functions):

export default React.createClass({
  render: function() {
     {* bunch of JSX goes here *}
  }
});

As requested, my index.html file:

<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <title>Consent Form</title>
  <meta name="description" content="Privacy Consent Webform">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!--Google Material Design Icons-->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
  <div id="app"></div>
</body>
</html>

The html doesn't have the bundle as a script tag because of my webpack config (the bundle is injected!)(the following code is just a piece of the config):

entry: [
    'webpack-hot-middleware/client',
    'bootstrap-loader',
    path.join(__dirname, 'src/main.js')
  ],
  output: {
    path: path.join(__dirname, '/dist/'),
    filename: '[name].js',
    publicPath: '/'
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.tpl.html',
      inject: 'body',
      filename: 'index.html'
    })
2
your issue may very well be in your index.html with your script tag to include your bundle. Can you please post that as well just to be sure?Chaim Friedman
@promisified sure! i've edited my questionykadaru
Can you include your static file server setup? Are you getting any errors in your client console?Hal Carleton
Also, what version of react-router are you using? You have react-router-v4 and react-router-dom as tags, but it looks like you're using a pre-4 version of react-router based on the api you are using.Hal Carleton
@HalCarleton "react-router": "^2.0.0", "react-router-dom": "^4.1.1". Should I be using 'react-router-dom'? I'm really confused. When I import the same components from 'react-router-dom' I get a bunch of weird errors like this person github.com/ReactTraining/react-router/issues/1799ykadaru

2 Answers

1
votes

When you add new routes to your app, you can't rely on hot reloading to inject the new route + components. I had to CTRL+C and run npm start again.

This solves the issue!!

Also react-router-dom is a React Router v4 package while react-router is an older version. Thanks to @HalCarleton for pointing that out. I saw code examples everywhere with react-router while the official documentation showed react-router-dom and I was really confused as to why there were two different types of packages.

1
votes

Try to do somethin like this:

<Switch>
      <Route path="/auth/login/:token" render={props => <Login  {...this.props} {...props}/>}/>
      <Route path="/auth/login" component={Login}/>
   </Switch>

First the route with the parameter and after the route without parameter. Inside my Login component I put this console.log(props.match.params.token); to test and worked for me.