Reputation: 916
I have a route configuration that looks like this (showing only the parts that I think may be relevant):
var React = require('react');
var Router = require('react-router');
var { Route, DefaultRoute, NotFoundRoute } = Router;
var routes = (
<Route handler={AppHandler}>
<DefaultRoute handler={HomeHandler}/>
<Route name='home' path='/home' handler={HomeHandler}/>
<Route name='settings' path='/settings/?:tab?' handler={SettingsHandler}/>
<NotFoundRoute handler={NotFoundHandler}/>
</Route>
);
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.getElementById('application'));
});
Now, on my Settings react file, I have the following:
var Settings = React.createClass({
mixins: [Router.State],
render: function() { ... }
});
If I access the host.local/settings
and log this.getParams()
everything works fine and the file renders showing me Object {tab: undefined}
in the console. But as soon as I try host.local/settings/user
- where I expected the console to return something like Object {tab: 'user'}
-, the whole thing crashes somewhere and just starts throwing Uncaught SyntaxError: Unexpected token <
in the console.
React is still young and therefore the errors are rather vague in many situations.
I've followed the specifications provided on the Path Matching Guide and it seems pretty standard, so I can only assume it's a problem with react-router itself or am I missing something?
tl;dr: It's not a problem with react-router.
Long version:
Apparently, it turns out the issue is not on ReactJS neither React-Router themselves. It involves mostly a bug on gulp-webserver (which I'm using for developing using proxies to connect separate projects running in parallel) and triggers an error when URLs are typed directly on the browser instead of being accessed through a link.
I did a test and it works fine when navigating, but crashes when accessed directly as described on this github issue, which basically renders my functional deeplink tests unviable, but should work when in production.
tl;dr: It's not a problem with gulp-webserver either.
In my case, it was related to relative
and absolute
paths and not any issue with gulp-webserver as mentioned before. To be more specific, I had to make sure your script and CSS references were absolute so that it doesn't try to find them in the path you're typing in the URL.
e.g.:
You have two URLs: /settings
and /settings/account
. In that case, if you have your script inclusion in the fallback file being something like <script src="scripts/main.js"></script>
, the server will return a 404 for it, since there's no file in /settings/scripts/main.js
.
Dumb of me, but in case anyone else falls for that, I hope this helps.
Upvotes: 43
Views: 10361
Reputation: 53169
Thanks for your analysis, it helped me to realize it wasn't an issue with React Router but my own paths.
I added <base href="/" />
into the <head>
of my index.html
and it worked (:
Edit for React Router 3:
Since early 2016, React Router will show a warning when you set <base>
:
Warning: Automatically setting basename using <base href> is deprecated
and will be removed in the next major release. The semantics of <base href>
are subtly different from basename. Please pass the basename explicitly in the
options to createHistory
It's better to do something like this instead:
const history = useRouterHistory(createHistory)({
basename: '/'
});
Upvotes: 48
Reputation: 1141
I am not encountering the error that you're seeing. It seems like your code is all right, so it's probably something that you didn't paste.
giving the information, I've build a quick project according to your spec and here's my setup
'use strict';
var React = require('react'),
Router = require('react-router'),
AppHandler = require('./pages/app.js'),
HomeHandler = require('./pages/home.js'),
SettingsHandler = require('./pages/setting.js'),
NotFoundHandler = require('./pages/not-found.js'),
Route = Router.Route,
NotFoundRoute = Router.NotFoundRoute,
DefaultRoute = Router.DefaultRoute,
Routes;
Routes = (
/* jshint ignore:start */
<Route handler={AppHandler}>
<DefaultRoute handler={HomeHandler}/>
<Route name='home' path='/home' handler={HomeHandler}/>
<Route name='settings' path='/settings/?:tab?' handler={SettingsHandler}/>
<NotFoundRoute handler={NotFoundHandler}/>
</Route>
/* jshint ignore:end */
);
Router.run(Routes, Router.HistoryLocation, function (Handler, state) {
React.render(<Handler/>, document.body);
});
I'm skipping the home and not found since those are not the problem, here's my setup in settings.js
'use strict';
var React = require('react')
Router = require('react-router');
var Setting = React.createClass({
mixins: [Router.State],
componentDidMount: function() {
//console.log(this.getParams());
},
render: function() {
/* jshint ignore:start */
console.log(this.getParams());
return (
<div>this is setting</div>
);
/* jshint ignore:end */
}
});
module.exports = Setting;
hope these will help
Upvotes: 1