Skip to content

Latest commit

 

History

History
202 lines (153 loc) · 4.57 KB

routing.md

File metadata and controls

202 lines (153 loc) · 4.57 KB

Routing

react-router is the de-facto standard routing solution for react applications. The thing is that with redux and a single state tree, the URL is part of the state. react-router-redux takes care of synchronizing the location of our application with the application state.

See the react-router-redux docs ➝ for more information.

Usage

To add a new route, use the generator npm run generate route.

This is what a generated route looks like for a container:

{
  path: '/',
  name: 'home',
  getComponent(nextState, cb) {
    const importModules = Promise.all([
      System.import('containers/HomePage')
    ])

    const renderRoute = loadModule(cb)

    importModules.then(([component]) => {
      renderRoute(component)
    })

    importModules.catch(errorLoading)
  }
}

To go to a new page use the push function by react-router-redux:

import { push } from 'react-router-redux'

dispatch(push('/some/page'))

Child Routes

npm run generate route does not currently support automatically generating child routes if you need them, but they can be easily created manually.

For example, if you have a route called about at /about and want to make a child route called team at /about/our-team you can just add that child page to the parent page's childRoutes array:

/* your app's other routes would already be in this array */
{
  path: '/about',
  name: 'about',
  getComponent(nextState, cb) {
    const importModules = Promise.all([
      System.import('containers/AboutPage')
    ])

    const renderRoute = loadModule(cb)

    importModules.then(([component]) => {
      renderRoute(component)
    })

    importModules.catch(errorLoading)
  },
  childRoutes: [
    {
      path: '/about/our-team',
      name: 'team',
      getComponent(nextState, cb) {
        const importModules = Promise.all([
          System.import('containers/TeamPage')
        ])

        const renderRoute = loadModule(cb)

        importModules.then(([component]) => {
          renderRoute(component)
        })

        importModules.catch(errorLoading)
      }
    }
  ]
}

Index routes

To add an index route, use the following pattern:

{
  path: '/',
  name: 'home',
  getComponent(nextState, cb) {
    const importModules = Promise.all([
      System.import('containers/HomePage')
    ])

    const renderRoute = loadModule(cb)

    importModules.then(([component]) => {
      renderRoute(component)
    })

    importModules.catch(errorLoading)
  },
  indexRoute: {
    getComponent(partialNextState, cb) {
      const importModules = Promise.all([
        System.import('containers/HomeView')
      ])

      const renderRoute = loadModule(cb)

      importModules.then(([component]) => {
        renderRoute(component)
      })

      importModules.catch(errorLoading)
    }
  }
}

Dynamic routes

To go to a dynamic route such as post/:slug e.g. 'post/cool-new-post', firstly add the route to your routes.js:

path: '/posts/:slug',
name: 'post',
getComponent(nextState, cb) {
 const importModules = Promise.all([
   System.import('containers/Post/reducer'),
   System.import('containers/Post/sagas'),
   System.import('containers/Post')
 ])

 const renderRoute = loadModule(cb)

 importModules.then(([reducer, sagas, component]) => {
   injectReducer('post', reducer.default)
   injectSagas(sagas.default)
   renderRoute(component)
 })

 importModules.catch(errorLoading)
}

###Container:

<Link to={`/posts/${post.slug}`} key={post._id}>

Clickable link with payload (you could use push if needed).

###Action:

export function getPost(slug) {
  return {
    type: LOAD_POST,
    slug
  }
}

export function postLoaded(post) {
  return {
    type: LOAD_POST_SUCCESS,
    podcast
  }
}

###Saga:

const { slug } = yield take(LOAD_POST)
yield call(getXhrPodcast, slug)

export function* getXhrPodcast(slug) {
  const requestURL = `http://your.api.com/api/posts/${slug}`
  const post = yield call(request, requestURL)
  if (!post.err) {
    yield put(postLoaded(post))
  } else {
    yield put(postLoadingError(post.err))
  }
}

Wait (take) for the LOAD_POST constant, which contains the slug payload from the getPost() function in actions.js.

When the action is fired then dispatch the getXhrPodcast() function to get the response from your API. On success dispatch the postLoaded() action (yield put) which sends back the response and can be added into the reducer state.

You can read more in react-router's docs ➝.