git.fiddlerwoaroof.com
README.md
f464bb7a
 # Routedux — Routes the Redux Way [![npm version](https://badge.fury.io/js/routedux.svg)](https://badge.fury.io/js/routedux) [![Build Status](https://travis-ci.org/cjdev/routedux.svg?branch=master)](https://travis-ci.org/cjdev/routedux) 
30db14b1
 
f464bb7a
 <img alt="Route Dux" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Ducks_crossing_the_road_sign.png/92px-Ducks_crossing_the_road_sign.png" align="right" />
1b712626
 
f464bb7a
 Routedux (:duck: :duck: :duck:) routes URLs to Redux actions and vice versa. 
 
 Your application doesn't need to know it lives in a browser, but your users want pretty urls and deep links. 
30db14b1
 
ce08d9fd
 ## Wait, my application doesn't need to know it lives in a browser?
30db14b1
 
ce08d9fd
 URLs are great for finding things on the internet.  But a single page application is not the same as a collection of 
 resources that lives on a remote server.
1b712626
 
ce08d9fd
 A single page application is a web application only in the sense that it lives on the web.  URLs are are not essential
 to it working well.  
 
 URLs give users accessing your application in a browser the ability to bookmark a particular view in your application
 so that their expectation of browser-based applications will continue to work.
 
 We think that's a good thing, but we also don't think the idea of url paths should be littered through your application.
 
 When you are developing a redux application, you want your UI to be a pure function of the current state tree.  
30db14b1
 
ce08d9fd
 By adding routes to that, it makes it harder to test.  And this difficulty can be compounded by other decisions about how
f464bb7a
 to add routes to your application. 
30db14b1
 
ce08d9fd
 ## An alternative approach
30db14b1
 
ce08d9fd
 React Router is the currently-accepted way to do URL routing in React applications.  For a standard React application without
 Redux, this solution isn't too bad.  But once you add Redux, things get difficult.
30db14b1
 
ce08d9fd
 We basically discovered the same lessons as Formidable Labs: [React Router is the wrong way to route in Redux apps.](http://formidable.com/blog/2016/07/11/let-the-url-do-the-talking-part-1-the-pain-of-react-router-in-redux/)
 
 However, we don't think their solution ([redux-little-router](https://github.com/FormidableLabs/redux-little-router)) 
 goes far enough, as it still embeds the idea of routes throughout your user interface.
 
 Once you separate URLs from your application state, you can easily port it to other environments that don't know what
 URLs are, and by simply removing the routing declaration, things will work as before.  
30db14b1
 
1b712626
 As an added (and we think absolutely essential) benefit, your entire application becomes easier to test, as rendering
ce08d9fd
 is a pure function of Redux state, and model logic and route actions are entirely encapsulated in Redux outside of the app.
30db14b1
 
ce08d9fd
 ## Simple Routing in 25 lines
30db14b1
 
 ```javascript
75dfd458
 import installBrowserRouter from 'routedux';
30db14b1
 import {createStore, compose, applyMiddleware} from 'redux';
 
 const LOAD_USER = 'LOAD_USER';
 
 function currentUserId() {
   return 42;
 };
 
 function reduce(state = initialState(), action) {
   ...
 }
 
 const routesConfig = [
   ['/user/:id', LOAD_USER, {}],
   ['/user/me', LOAD_USER, {id: currentUserId()}],
   ['/article/:slug', 'LOAD_ARTICLE', {}],
   ['/', 'LOAD_ARTICLE', {slug: "home-content"}]
 ];
 
 const {enhancer, middleware} = installBrowserRouter(routesConfig);
 
 const store = createStore(reduce, compose(
   enhance,
   applyMiddleware(middleware)
 ));
 
 ```
 
 Any time a handled action fires the url in the address bar will change, and if the url in the address bar changes
 the corresponding action will fire (unless the action was initiated by a url change).
 
 
ce08d9fd
 ## Route matching precedence - which route matches best?
30db14b1
 
1b712626
 Route precedence is a function of the type of matching done in each segment and the order in which the wildcard segments
 match.  Exact matches are always preferred to wildcards moving from left to right.  
 
 ```javascript
 
     const routesInOrderOfPrecedence = [
       
       ['/user/me/update', '/user/me'], // both perfectly specific - will match above any wildcard route
       '/user/me/:view',
       '/user/:id/update', // less specific because 'me' is exact match, while :id is a wildcard
       '/user/:id/:view'
     ];
 
 ```
 
ce08d9fd
 ## Fragment component
30db14b1
 
1b712626
 ```javascript
 
 const state = {
   menu: ...
 }
 
 const view = (
   <PageFrame>
       <Fragment state={state} filterOn="menu">
         <Menu />
       </Fragment>
   </PageFrame>
 )
 
 // If menu is truthy, this renders as:
 
 (
   <PageFrame>
     <Menu />
   </PageFrame>
 )
 
 // If menu is falsy, this renders as:
 (
   <PageFrame>
   </PageFrame>
 )
 
 // If property is missing in path, it's falsy.
 
 const view = (
   <PageFrame>
       <Fragment state={state} filterOn="menu.missingProp.something">
         <Menu />
       </Fragment>
   </PageFrame>
 )
 
 // Renders as: 
 (
   <PageFrame>
   </PageFrame>
 )
 
 ```
 
ce08d9fd
 Given that every UI state will be in your state tree as a function of your reducer logic, you can express any restriction
 on which parts of the UI display, even those that have nothing to do with the specific transformations caused by 
 your URL actions.
30db14b1
 
922499e3
 See also the demo site in the `demos/` directory, to see routedux used in an application.