Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Routing Issues in React-Redux

Tags:

react-redux

I'm new to the React-Redux ecosystem, learning by trying out simple applications. In this case I'm trying out how routing works in the react-redux application. Basically, the idea is :

  1. Navigate to a new page by clicking a Link( a react-router component)
  2. Navigate to a new page upon successful completion of dispatched async action.

Here's my code

import React from 'react'
import {Link} from 'react-router'
import {routerActions} from 'react-router-redux'
import {connect} from 'react-redux'

class App extends React.Component {
  render() {
    // And you have access to the selected fields of the State too!
    return (
        <div>
            <header>
                Links:
                {' '}
                <Link to="/">Home</Link>
                {' '}
                <Link to="/foo">Foo</Link>
                {' '}
                <Link to="/bar">Bar</Link>
            </header>
            <div>
                <button onClick={() => routerActions.push('/foo')}>Go to /foo</button>
            </div>
        </div>
    )
  }
}
export default connect(null, null)(App);
===================================================================
import React from 'react'
import {connect} from 'react-redux'

class Foo extends React.Component {
  render() {
    return (
        <div> <h1>I'm Foo</h1> </div>
    )
  }
}
export default connect(null, null)(Foo);
===================================================================
import React from 'react'
import {connect} from 'react-redux'
class Bar extends React.Component {
  render() {
    return (
        <div> <h1>I'm bar</h1> </div>
    )
  }
}
export default connect(null, null)(Bar);

===================================================================
import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import {Router, Route, browserHistory} from 'react-router'
import {syncHistoryWithStore} from 'react-router-redux'
import configureStore from './store'
import App from './components/test/App';
import Bar from './components/test/Bar';
import Foo from './components/test/Foo';
// Get the store with integrated routing middleware.
const store = configureStore()
// Sync browser history with the store.
const history = syncHistoryWithStore(browserHistory, store)
// And use the prepared history in your Router
ReactDOM.render(
  <Provider store={store}>
    <div>
        <Router history={history}>
            <Route path="/" component={App}>
                <Route path="/foo" component={Foo}/>
                <Route path="/bar" component={Bar}/>
            </Route>
        </Router>
    </div>
  </Provider>,
  document.getElementById('root')
===================================================================

import {combineReducers,createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import userReducer from './reducers/reducer-user';
import {routerMiddleware,routerReducer} from 'react-router-redux'
import {browserHistory} from 'react-router'

export default function configureStore() {
    // Create the routing middleware applying it history
    const browserMiddleware = routerMiddleware(browserHistory);
    const logger = createLogger();
    const reducer = combineReducers({
      userState: userReducer,
      routing: routerReducer
    })
    const store = createStore(reducer,applyMiddleware(thunk,browserMiddleware,logger));
    return store;
}

The application builds fine and it comes up well but when i click on the link, it does not work.
See screen shot of the running application
Searched around and read various posts but i could not pinpoint the root problem.

like image 445
vgsingh Avatar asked Jun 01 '16 19:06

vgsingh


1 Answers

Your code seems to be correct, but there is a simple thing you are missing: you are not rendering the "child" of your router! :)

You can check that out here:

https://github.com/reactjs/react-router-tutorial/tree/master/lessons/04-nested-routes#sharing-our-navigation

Whenever you want to render a component route (the one you declared using </Route path="application-path" component={MyComponent} />), you need to specify where it will be placed. Using react-router, you specify this using the children prop. Then, whenever React "sees" this prop, it will render your routes (it can be a nested route too).

So, to fix your code, your App component needs to handle this.props.children correctly. Something like that:

class App extends React.Component {
   /* ... */
   render() {
       return (
           <div>
               <header>Links go here</header>
               {this.props.children}
           </div>
       )
   }
}

Now, when you hit "/foo" route, this.props.children will be replaced by Foo component.

By the way, your nested routes (those inside ) don't need to have "/", since they will be "prepended". This is the way react-router render nested routes.

I think that is it, good luck with that! :)

like image 108
William Martins Avatar answered Oct 07 '22 01:10

William Martins