3
votes

I have paths that I want React Router to handle, and I also have an express API backend that I call from the React app to do some secure API calls.

/#/ - want app served here
/#/:id - unique URLs for the app, i use the ID to call certain express endpoints from React.
* - all express REST endpoints

Express app.js:

app.use(middleware);
app.use(require('webpack-hot-middleware')(compiler, {
  log: console.log
}));
app.use('/api', [router_invokeBhApi]);
app.get('/#/*', function response(req, res) {
  res.write(middleware.fileSystem.readFileSync(path.join(__dirname, 'dist/index.html')));
  res.end();
});
app.use(express.static(path.join(__dirname, '/dist')))

My React router component:

export default (
  <Route path="/" component={App}>
    <IndexRoute component={HomePage} />
    <Route path="/:id" component={ConsentForm} something="dope"/>
  </Route>
);

So here's what's happening:
- going to localhost:8000 serves the app with the HomePage component
- going to localhost:8000/#/ also serves the app with the HomePage component
- going to localhost:8000/example gives me Cannot GET /example which means express is working
- going to localhost:8000/api gives me a test JSON object which i send from express, which is correct.
- going to localhost:8000/#/somehashcode STILL gives me the HomePage component, when it SHOULD be giving me the ConsentForm component.

I inspected the Router component using React Dev tools:
- the RouterContext component has an object called routes with a childRoutes inside the routes[0], and it has the path /:id. routes[0] also has a path / which tells me React Router loaded all the routes correctly??

So confused...

React file where I render the whole app:

import 'babel-polyfill';

import React from 'react';
import ReactDOM from 'react-dom';
import { Router, browserHistory } from 'react-router';

import Routes from './shared/components/Routes';

import './shared/base.css';
import './shared/customInput.css';


const ROOT_ELEMENT = 'app';

ReactDOM.render((
  <Router history={browserHistory}>
    {Routes}
  </Router>
), document.getElementById(ROOT_ELEMENT));
2
Can you provide some more information on the version of react-router you're using? According to their latest docs you have to use HashRouter, rather than just Route, from one of their packages. reacttraining.com/react-router/web/api/HashRouter - Michael
@Michael "react": "^0.14.7", "react-bootstrap": "^0.28.3", "react-dom": "^0.14.7", "react-router": "^2.0.0", "react-router-dom": "^4.1.1", - ykadaru
What's the render method of App look like? Do you have a spot to correctly render the child components? - Jake Haller-Roby
@gravityplanx I've updated the question with it - ykadaru
Still not including the info I was asking for though. I'm asking specifically about the react component named App. Does it's render method include a space for a child component? - Jake Haller-Roby

2 Answers

1
votes

I finally figured it out!

In the React Router component change the :id route to:

<Route path="/redirect/:id" component={ConsentForm} something="dope"/>

In Express, app.js change the React serve to:

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

Learnt 2 things from this:
- Using # in the route doesn't work. Not sure why.
- Explicitly state the route in the React side as well.

Quite weird, or maybe I'm going off some half-baked knowledge. Any resource to point me in the right direction would be so awesome.

Pretty sure someone else is going to run into this as they use Express and React together.

0
votes

Found your problem.

You're using BrowserHistory in your configuration. This option (the recommended one at present) does not use a hash in the uri, but instead directly integrates with the browser.

Try hitting your app at localhost:8000/somehashcode and see what you get.