I'm using React-Router 1.0.0-rc3 together with Redux-Router 1.0.0-beta3.
When using React-Router, you can use useBasename
with createHistory
to set the base URL for an app, so that you can easily write an app that runs inside a subdirectory. Example:
Instead of this:
import { createHistory } from 'history';
let base = "/app_name/"
<Router history={browserHistory}>
<Route path={base} component={App}></Route>
</Router>
<Link path={base + "some_path"}>some_path</Link>
You can write in this way using useBasename
:
import { createHistory, useBasename } from 'history';
const browserHistory = useBasename(createHistory)({
basename: "/app_name"
});
<Router history={browserHistory}>
<Route path="/" component={App}></Route>
</Router>
<Link path="/some_path">some_path</Link>
However, in Redux-Router, you need to pass createHistory
instead of history
to a reducer:
const store = compose(
applyMiddleware(m1, m2, m3),
reduxReactRouter({
routes,
createHistory
}),
devTools()
)(createStore)(reducer);
How can we use useBasename
in this case?
To add the link in the menu, use the <NavLink /> component by react-router-dom . The NavLink component provides a declarative way to navigate around the application. It is similar to the Link component, except it can apply an active style to the link if it is active.
The connect() function connects a React component to a Redux store. It provides its connected component with the pieces of the data it needs from the store, and the functions it can use to dispatch actions to the store.
For react-router v2 or v3 and using react-router-redux v4 instead of redux-router, the setup of the history object will look like this:
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'
const browserHistory = useRouterHistory(createHistory)({
basename: '<yourBaseUrl>'
})
const history = syncHistoryWithStore(browserHistory, store)
The rest of the setup is as usual when there is no extra base URL.
You can create a function that wraps useBasename
:
const createHistoryWithBasename = (historyOptions) => {
return useBasename(createHistory)({
basename: '/app_name',
...historyOptions
})
}
And pass it to compose
:
const store = compose(
applyMiddleware(m1, m2, m3),
reduxReactRouter({
routes,
createHistory: createHistoryWithBaseName
}),
devTools()
)(createStore)(reducer);
The API changes very often so this is what worked for me (I'm using the 2.0.3
version of redux-simple-router
). I have defined the custom history in a separate file:
import { useRouterHistory } from 'react-router'
import { createHistory, useBasename } from 'history'
import { baseUrl } from '../config'
const browserHistory = useRouterHistory(useBasename(createHistory))({
basename: "/appgen"
});
Now I need to initialize the store:
import { syncHistory, routeReducer } from 'redux-simple-router'
import browserHistory from '../misc/browserHistory'
const rootReducer = combineReducers({
// ...other reducers
routing: routeReducer
});
const reduxRouterMiddleware = syncHistory(browserHistory);
const finalCreateStore = compose(
// ...other middleware
applyMiddleware(reduxRouterMiddleware),
)(createStore);
const store = finalCreateStore(rootReducer, initialState);
Eventually, you need to pass the history
to the Router
.
import browserHistory from './misc/browserHistory'
import routes from '../routes'
export default class Root extends Component {
static propTypes = {
history: PropTypes.object.isRequired
};
render() {
return (
<Router history={browserHistory}>
{routes}
</Router>
)
}
}
Before I came up with this, I was using a manual solution. I defined my own Link
component and my own redux action that were responsible for prepending the base URL. It might be useful for someone.
Updated Link
component:
import React, { Component } from 'react'
import { Link as RouterLink } from 'react-router'
import { baseUrl } from '../config'
export default class Link extends Component {
render() {
return <RouterLink {...this.props} to={baseUrl + '/' + this.props.to} />
}
}
Custom action creator:
import { routeActions } from 'redux-simple-router'
import { baseUrl } from '../config'
export function goTo(path) {
return routeActions.push(baseUrl + '/' + path);
}
Updated root route:
import { baseUrl } from './config'
export default (
<Route component={App} path={baseUrl}>
//...nested routes
</Route>
);
Note that these custom tools only support pushing updated paths, not the location descriptor object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With