React Redux and react-router-dom

Kaiser Soze picture Kaiser Soze · May 6, 2017 · Viewed 9.7k times · Source

I am learning Redux, and with the new changes in react-router-dom I am a bit confused. I have these files:

Index.js

import React from 'react';
import { Provider } from 'react-redux';
import ReactDOM from 'react-dom';
//  import { AppContainer } from 'react-hot-loader';
import App from './containers/App';
import store from './store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root'),
);

App.js

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from '../actions/actionCreators';
import Main from '../components/Main';

function mapStateToProps(state) {
  return {
    search: state.search,
    navigation: state.navigation,
  };
}
export function mapDispatchToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch);
}
const App = connect(mapStateToProps, mapDispatchToProps)(Main);
export default App;

Finally, Main.js

import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Header from './Header';
import Footer from './Footer';
import Listing from './Listing';
import SingleListing from './SingleListing';
const Main = () => (
  <Router>
    <div className="wrapper">
     <Header />
      <Route exact path="/" component={Listing} />
      <Route path="/list" component={SingleListing} />
      <Footer />
    </div>
  </Router>
);

export default Main;

This code works just fine, when I go to localhost:3000/list or if I click on a it works.

However I have the feeling that I am doing something wrong and that the correct way should be to wrap in to the inside index.js

so I should do something like this:

<Router>
  <Provider store={store}>
    <App />
  </Provider>,
</Router>   

document.getElementById('root'),

And then in Main.js

<div className="wrapper">
  <Header />
  <Route exact path="/" component={Listing} />
  <Route path="/list" component={SingleListing} />
  <Footer />
</div>

However when I do this, if I go directly to the link localhost/list I can see the component, but if I clink on any link nothing happens.

I am confused on how to correctly use the router with redux. This is the code I am using inside reducers/index.js

import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import search from './search';
import navigation from './navigation';

const rootReducer = combineReducers({ search, navigation, routing: routerReducer });

export default rootReducer;

I have researched this site and many tutorials online and on youtube, but I don't understand if I am doing correctly in my code, I know it works but I am interested in learning if this is the correct way. Thank you!

Answer

Sammy I. picture Sammy I. · May 6, 2017

Yes, you are writing router correctly. Your concern is understandable. Until the version 4.0.0, react-router had a different way to declare routes. You would define a Router like in your second example, but instead of defining routes in the components, you would define routes within the Router. Here's an example of react-router before 4.0.0:

App.js:

//<boilerplate imports>

import Home from './components/Home';
import router from './router';
import './index.css';

ReactDOM.render(
  <Router router='router' history='browserHistory'>
  </Router>,
  document.getElementById('root')
);

router.js:

//<boilerplate imports>

import Photographer from './components/photographer/Photographer';
import Developer from './components/developer/Developer';
import Home from './components/Home';

export default (
    <Route path="/">
        <IndexRoute component={Home} />
        <Route path="photographer" component={Photographer} />
        <Route path="developer" component={Developer} />
    </Route>
);

You would define the router and all the routes, subroutes, and components to use in one place, and you would end up providing that to ReactDOM.render()

Having said that, the first way to do things is correct and is the way the people behind React Router expect people to use the interface.

Regarding the last question, are you getting an error with that code using react-router-redux? Looking at this for reference, it seems to be correct.