Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
For the current version 0.11 and forward, you need to add Router.HistoryLocation to Router.run(). <Routes> are now deprecated. See the Upgrade Guide for the 0.12.x HistoryLocation implementation.
Another way to handle what to display after the hash (so if you don't use pushState !) is to create your CustomLocation and load it at ReactRouter creation.
For exemple, if you want to have hashbang url (so with #!) to comply with google specs for crawling, your can create a HashbangLocation.js file which mainly copy the original HashLocation such as :
'use strict';
var LocationActions = require('../../node_modules/react-router/lib/actions/LocationActions');
var History = require('../../node_modules/react-router/lib/History');
var _listeners = [];
var _isListening = false;
var _actionType;
function notifyChange(type) {
if (type === LocationActions.PUSH) History.length += 1;
var change = {
path: HashbangLocation.getCurrentPath(),
type: type
};
_listeners.forEach(function (listener) {
listener.call(HashbangLocation, change);
});
}
function slashToHashbang(path) {
return "!" + path.replace(/^\//, '');
}
function ensureSlash() {
var path = HashbangLocation.getCurrentPath();
if (path.charAt(0) === '/') {
return true;
}HashbangLocation.replace('/' + path);
return false;
}
function onHashChange() {
if (ensureSlash()) {
// If we don't have an _actionType then all we know is the hash
// changed. It was probably caused by the user clicking the Back
// button, but may have also been the Forward button or manual
// manipulation. So just guess 'pop'.
var curActionType = _actionType;
_actionType = null;
notifyChange(curActionType || LocationActions.POP);
}
}
/**
* A Location that uses `window.location.hash`.
*/
var HashbangLocation = {
addChangeListener: function addChangeListener(listener) {
_listeners.push(listener);
// Do this BEFORE listening for hashchange.
ensureSlash();
if (!_isListening) {
if (window.addEventListener) {
window.addEventListener('hashchange', onHashChange, false);
} else {
window.attachEvent('onhashchange', onHashChange);
}
_isListening = true;
}
},
removeChangeListener: function removeChangeListener(listener) {
_listeners = _listeners.filter(function (l) {
return l !== listener;
});
if (_listeners.length === 0) {
if (window.removeEventListener) {
window.removeEventListener('hashchange', onHashChange, false);
} else {
window.removeEvent('onhashchange', onHashChange);
}
_isListening = false;
}
},
push: function push(path) {
_actionType = LocationActions.PUSH;
window.location.hash = slashToHashbang(path);
},
replace: function replace(path) {
_actionType = LocationActions.REPLACE;
window.location.replace(window.location.pathname + window.location.search + '#' + slashToHashbang(path));
},
pop: function pop() {
_actionType = LocationActions.POP;
History.back();
},
getCurrentPath: function getCurrentPath() {
return decodeURI(
// We can't use window.location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
"/" + (window.location.href.split('#!')[1] || ''));
},
toString: function toString() {
return '<HashbangLocation>';
}
};
module.exports = HashbangLocation;
The answer to this question has changed dramatically over the years as React Router has been refactored again and again. Here is a breakdown of how to solve the issue with each version.
Version 6
The idea is to set the router to be a "browser router", which is created using the createBrowserRouter() function. This router is then added to the root element of the React app.
For the versions 1, 2 and 3 of React Router, the correct way to set the route to URL mapping scheme is by passing a history implementation into the history parameter of <Router>. From the histories documentation:
In a nutshell, a history knows how to listen to the browser's address bar for changes and parses the URL into a location object that the router can use to match routes and render the correct set of components.
In react-router 2 and 3, your route configuration code will look something like this:
You can actually use .htaccess to accomplish this. The browser normally needs the query string delimiter ? or # to determine where the query string begins and the directory paths end.
The end result we want is www.mysite.com/dir
So we need to catch the issue before the web server searches for the directory it thinks we asked for /dir.
So we place a .htaccess file in the root of the project.
# Setting up apache options
AddDefaultCharset utf-8
Options +FollowSymlinks -MultiViews -Indexes
RewriteEngine on
# Setting up apache options (Godaddy specific)
#DirectoryIndex index.php
#RewriteBase /
# Defining the rewrite rules
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^.*$ ./index.html
Then you obtain the query parameters with window.location.pathname
You can then avoid using react routes if you want and just manipulate the url and browser history if you want as well.
Hope this helps someone...