Releases: acdlite/redux-router
Another version comes along! (1.0.0-beta6)
We are glad to be able to continue bringing this project forward. A big "thank you" goes out to @mjrussell, who did most of work of this release and hopefully will continue to do so (no pressure).
Update react-router
We updated react-routers version to 1.0.3
and we are already working on upgrading to react-router
v2. As this upgrade will take some more work and testing, we chose to stay at v1.0.3
for now.
Update history
We removed the peerDependency
to history
as it did not work properly with older npm versions, also npm had a nasty bug with releasing modules containing history
. Internally we updated history to 1.17.0
.
Also we removed any direct import
or require
on our side, so s user has complete control over which createHistory
function is handed over. This applies mainly to the server-side rendering module, which had the only direct import. To prevent people from using too old versions of history, we included a sanity check which checks the ´history´ a user hands over to us for the necessary functions (see #221).
This breaks things on server-side rendering, as you now need to add a createHistory
function to the reduxRouter.
Check out the test to clarify things:
https://github.com/acdlite/redux-router/blob/master/src/__tests__/ReduxRouter-test.js#L201
Server-Side Rendering Example
We included a very basic server-rendering example to help people get started. Thanks to @stevoland.
v1.0.0-beta5
So this release basically bundles three PRs:
- #185:
When usinghistory
basename function it returns an object. Before this
it would only accept a function that returns an object. This update
gives users the ability to use other helpers provided by history.
Also take a look at the added test , it explains pretty well what´s possible now. - #183:
This fixes the infinite redirect loop in IE8&9 and also addresses some issues with router actions firing twice on the first load. We now got aINIT_ROUTES
action for the initial load. - #178:
This allows you to switch out the defaultRoutingContext
e.g. forRelayRoutingContext
.
Thanks again @apapirovski, @vslinko and @agirton-twitter for your contributions!
Also we added history
as a dependency. Tried it as a peerDependency
but this seems to cause problems with older npm
versions.
Also we want to bring #172 to your attention (again). We badly need contributions for redux-router, feel free to send us PRs or take part in the discussions on the issue trackers, if many people put in a little bit of effort it´ll be just as good as one full time contributor.
getRoutes() is back
It turns out that the dynamic routes feature from the last release won't work for server-side rendering, because the routes need to be specified before calling match()
. You must pass routes
(or getRoutes()
— see below) directly to the reduxReactRouter()
store enhancer when doing server-side rendering. We throw an error if you don't.
This makes circular dependencies (routes depend on store, store depends on routes) more difficult on the server, so this release also brings back a modified version of getRoutes()
.
reduxReactRouter({
getRoutes({ getState, dispatch }) {
// Return routes configuration
}
})
Note that you can always use a closure to work around a circular dependency:
let store;
function doSomethingOnEnter() {
store.dispatch(whatever);
}
const routes = (
<Route>
<Router path="/" onEnter={doSomethingOnEnter} />
</Route>
);
store = reduxReactRouter({ routes })(createStore)(reducer, initialState);
This is essentially what getRoutes()
does for you.
Thank you to everybody who has been testing the betas so we can identify and fix issues like these! I am optimistic about a stable 1.0 release coming out soon (or whenever React Router releases their 1.0).
Dynamic Route Configuration or: How I Learned to Stop Worrying and Love Circular Dependencies
Two big additions with this release.
Routes as children/props
Instead of passing your route configuration to the store enhancer, you now also have the option of passing it to <ReduxRouter>
as either the routes
prop or as children. This brings us in line with the normal React Router API.
Example:
ReactDOM.render((
<Provider store={store}>
<ReduxRouter>
<Route path="/" component={App}>
<Route path="parent" component={Parent}>
<Route path="child/:id" component={Child} />
</Route>
</Route>
</ReduxRouter>
</Provider>
), el);
or, equivalently:
const routes = (
<Route path="/" component={App}>
<Route path="parent" component={Parent}>
<Route path="child/:id" component={Child} />
</Route>
</Route>
);
ReactDOM.render((
<Provider store={store}>
<ReduxRouter routes={routes} />
</Provider>
), el);
This solves the circular dependency problem (#44), where if you needed a reference to the store from within a route transition hook, you had to use a closure. This was confusing and easy to mess up; the new API does this for you using React Router's built-in dynamic routes functionality.
As a bonus, the router will respond to new props, so hot reloading totally works.
Server-side rendering
To render an app on the server, import the reduxReactRouter
store enhancer from redux-react-router/server
instead of the main module. This is a slightly different version of the enhancer with server-specific functionality. Also import the match()
action creator:
import { match, reduxReactRouter } from 'redux-react-router/server';
Then set up your store like normal. You can omit createHistory
and history
if you like:
const store = compose(
applyMiddleware(m1, m2, m3),
reduxReactRouter()
)(createStore)(reducer);
The match()
action creator is very similar to the match()
function provided by React Router, except because it's an action creator, we dispatch the result. It accepts a URL and a callback:
store.dispatch(match('/some/path', (error, redirectLocation, routerState) => {
if (error) {
// handle error
}
if (redirectLocation) {
// handle redirect
}
if (!routerState) {
// handle 404
}
// Otherwise, render to string
res.send(
renderToString(
<Provider store={store}>
<Route path="/" component={App}>
<Route path="some" component={Parent}>
<Route path="path" component={Child} />
</Route>
</Route>
</Provider>
)
);
}));
Fix extra dispatch after external state change
Noticed after testing with Redux Devtools that an extra, unnecessary action was being dispatched after an external state change. This PR fixes it by comparing location state keys before calling locationDidChange().