Denis Yakovenko Denis Yakovenko - 1 year ago 92
Javascript Question

React Router is able to do the routing only if started from root url

I have a React app that also uses Redux and ReactRouter.

My problem is the following:

When I launch the app and go to the root url, I can normally navigate inside the app, and the routes in the navigation bar will be changing as I navigate.

However, if I type in the navigation bar any url other than the root, I get a weird error:
enter image description here
enter image description here

I don't really get how one can get such an error.

If I go to

and then click on the item with the link
, everything will be fine and the component will successfully get rendered. If I type
right away (or any other existing route) I get this error.

Here's how I initialize the react-router and define my routes:



import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, browserHistory } from 'react-router';
import reduxPromise from 'redux-promise';

import routes from './routes';
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware(

<Provider store={createStoreWithMiddleware(reducers)}>
<Router history={browserHistory} routes={routes} />
, document.querySelector('')


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

import App from './components/app';
import CarsIndex from './containers/cars-index';
import CarNew from './containers/car-new';
import CarShow from './containers/car-show';
import CarEdit from './containers/car-edit';
import SignIn from './containers/signin';
import auth from './auth/auth';

function requireAuth(nextState, replace) {
if (!auth.loggedIn()) {
pathname: '/authenticate',
state: { nextPathname: nextState.location.pathname }

function filterLoggedIn(nextState, replace) {
if (auth.loggedIn()) {
pathname: '/',
state: { nextPathname: nextState.location.pathname }

export default (
<Route path='/' component={App}>
<IndexRoute component={CarsIndex} onEnter={requireAuth} />
<Route path='cars/new' component={CarNew} onEnter={requireAuth} />
<Route path='cars/:id' component={CarShow} onEnter={requireAuth} />
<Route path='cars/edit/:id' component={CarEdit} onEnter={requireAuth} />
<Route path='authenticate' component={SignIn} onEnter={filterLoggedIn} />
<Redirect from='*' to='/' />

My server is a small express.js app and it redirects any requests other than
to the

Here's a part from my

const path = require('path');
const port = process.env.PORT || 1337;
const app = express();
const pathToStatic = path.join(__dirname, 'static');
express.static(path.join(__dirname, 'static'));
extended: true
app.get('/api/cars', (req, res) => {
return Car.find((err, cars) => {
if (!err) {
return res.send(cars);
} else {
res.statusCode = 500;
return res.send({ error: 'Server error' });
app.get('*', (req, res) => {
res.sendFile(path.resolve(pathToStatic, 'index.html'));

app.listen(port, () => {
console.log(`Express server is listening on port ${port}`);

Have you encountered such an issue? Could you help me to find out the soultion to this problem?

Answer Source

The screenshot shows that bundle.js (when requested) is returning index.html.

This is because your express routes handle route api/cars and then default everything else to index.html.

Of course all your resources that appear on index.html must also be sent the browser. This includes <script src="bundle.js"></script> which the browser will request once it gets index.html the first time.

So, you must have some way to allow express to handle requests for the resources that index.html needs.

A popular solution to this is to mount an assets directory and place that above the default route. Something like:

// api routes


// default route

Then make sure your bundle.js is inside the assets directory. And then that the script tag looks like <script src="/assets/bundle.js"></script>.