Introduction

In the previous article, we covered the Rematch framework, designed to lower the barrier-to-entry for JavaScript developers starting with Redux and functional programming.

While coding Rematch reducers is an easy task, in order to have a complete function application, programmers still need to integrate routing into their projects. A router creates a history object, which it uses to keep track of the current location and re-render the website whenever that changes. The other components provided by React Router rely on having that history object available through React context, so they must be rendered as descendants of a router component. A React Router component that does not have a router as one of its ancestors will fail to work.

Rematch documentation provides basic information on getting simple routing configured, using BrowserRouter from React Router v4.

Unfortunately, integrating Redux -aware ConnectedRouter is not covered by the documentation and is not straightforward due to multiple breaking changes in both React Router and Rematch API making the existing documentation and references unreliable.

Why ConnectedRouter?

ConnectedRouter is integrated directly with Redux state. Since Rematch is meant to be a better way of integrating Redux, it only makes to use the redux-aware router. ConnectedRouter is an awesome package providing us with history operations such as push, replace and go back. It stores history inside redux as an immutable object, supports hot-reload support and much more. ConnectedRouter is available for both React.JS and React Native, making it an excellent tool to master.

Working Example

ConnectedRouter has to be integrated with the Redux store. Let’s start with that.

import createHistory from 'history/createBrowserHistory'; import { connectRouter } from 'connected-react-router'; import { routerMiddleware } from 'react-router-redux'; import { init } from '@rematch/core'; import * as models from './models'; export const history = createHistory(); const middleware = routerMiddleware(history); const store = init({ models, redux: { reducers: { router: connectRouter(history) }, middlewares: [middleware] } }); export default store; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import createHistory from 'history/createBrowserHistory' ; import { connectRouter } from 'connected-react-router' ; import { routerMiddleware } from 'react-router-redux' ; import { init } from '@rematch/core' ; import * as models from './models' ; export const history = createHistory ( ) ; const middleware = routerMiddleware ( history ) ; const store = init ( { models , redux : { reducers : { router : connectRouter ( history ) } , middlewares : [ middleware ] } } ) ; export default store ;

Let’s define routes as below:

import React from 'react'; import { Route, Switch, Redirect } from 'react-router-dom'; import { ConnectedRouter as Router } from 'connected-react-router'; import { history } from './store'; import Login from './components/Auth/Login'; import PrivateRoute from './components/Auth/PrivateRoute'; import Reporter from './components/Reporter/Reporter'; import Layout from './components/UI/Layout'; import Brief from './components/Brief'; function Component404() { return ( <div className="error centered"> <span> <h1>Invalid url</h1> </span> </div> ); } export default () => ( <Layout> <Router history={history}> <Switch> <Route path="/login" component={Login} /> <PrivateRoute path="/reporter" component={Reporter} /> <PrivateRoute path="/brief" component={Brief} /> <Route exact path="/" component={() => <Redirect to="/reporter" />} /> <Route component={Component404} /> </Switch> </Router> </Layout> ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import React from 'react' ; import { Route , Switch , Redirect } from 'react-router-dom' ; import { ConnectedRouter as Router } from 'connected-react-router' ; import { history } from './store' ; import Login from './components/Auth/Login' ; import PrivateRoute from './components/Auth/PrivateRoute' ; import Reporter from './components/Reporter/Reporter' ; import Layout from './components/UI/Layout' ; import Brief from './components/Brief' ; function Component404 ( ) { return ( < div className = "error centered" > < span > < h1 > Invalid url < / h1 > < / span > < / div > ) ; } export default ( ) = > ( < Layout > < Router history = { history } > < Switch > < Route path = "/login" component = { Login } / > < PrivateRoute path = "/reporter" component = { Reporter } / > < PrivateRoute path = "/brief" component = { Brief } / > < Route exact path = "/" component = { ( ) = > < Redirect to = "/reporter" / > } / > < Route component = { Component404 } / > < / Switch > < / Router > < / Layout > ) ;

Now, let’s integrate the above routes into our application.

import React from 'react'; import { Provider } from 'react-redux'; import store from './store'; import Routes from './routes'; const rootElement = document.getElementById('root'); render( <Provider store={store}> <Routes /> </Provider>, document.getElementById('root') ); 1 2 3 4 5 6 7 8 9 10 11 12 import React from 'react' ; import { Provider } from 'react-redux' ; import store from './store' ; import Routes from './routes' ; const rootElement = document . getElementById ( 'root' ) ; render ( < Provider store = { store } > < Routes / > < / Provider > , document . getElementById ( 'root' ) ) ;

Looking for more React.JS, React-Native, Node.JS tutorials, want us to cover a specific subject in our blog, or looking for assistance with your project? Please fill out the contact form.