Skip to content

Latest commit

 

History

History
79 lines (59 loc) · 2.45 KB

File metadata and controls

79 lines (59 loc) · 2.45 KB

Redux & React Router universal app

A simple example for doing data fetching and rendering in a universal (aka isomorphic) app with React Router and Redux.

Setup

Clone the repo then:

npm install
npm start

Description

The example uses the GitHub API for demonstrating how async Redux actions can work together with React Router server side and client rendering.
For the sake of simplicity it's also using redux-actions and redux-promise.

These are the most important aspects of this approach:

  • universal: setting redux actions for data fetching as props on the routes, as seen here:
<Route path="/" component={App} action={actions.getContribs}>
  <Route path="user/:name" component={User} action={actions.getUser} />
</Route>
  • server: collecting all actions, dispatching them and waiting for all of them to settle before rendering the matched route server side, as seen here:
dispatchRouteActions: ({routes, params}, store) ->
  actions = for route in routes when route.action?
    store.dispatch route.action.call(this, params)
  Promise.all(actions)

...

dispatchRouteActions(renderProps, store).then ->
  props = assign {}, renderProps, {store}
  element = React.createElement(RoutingContext, props)
  html = renderToString(element)
  app = appTemplate(html, store.getState())
  res.send(app)
  • client: dispatching a route's action when entering it by setting the onEnter prop on every route that has an action prop, as seen here:
createRoutes: (routes, store, currentPathname) ->
  dispatchAction = ({location: {pathname}, params}) ->
    if pathname isnt currentPathname
      store.dispatch @action.call(this, params)
    currentPathname = pathname

  createRoutes(routes).map set = (route) ->
    {action, onEnter, childRoutes} = route
    onEnter ?= dispatchAction if action?
    childRoutes = childRoutes?.map(set)
    assign {}, route, {onEnter, childRoutes}

...

routes =  createRoutes(routes, store, document.location.pathname)

Troubleshooting

  • if data is not loading anymore it's possible you exceeded GitHub's API rate limit of 60 calls/hour