|
1 | 1 | React Router in a Flux App
|
2 | 2 | ==========================
|
3 | 3 |
|
4 |
| -```js |
5 |
| -// router.js |
6 |
| -var routes = require('./routes'); |
7 |
| -var Router = require('react-router'); |
8 |
| - |
9 |
| -// we can create a router before "running" it |
10 |
| -var router = Router.create({ |
11 |
| - routes: routes, |
12 |
| - location: Router.HistoryLocation |
13 |
| -}); |
| 4 | +Circular Dependencies in Actions |
| 5 | +-------------------------------- |
14 | 6 |
|
15 |
| -module.exports = router; |
16 |
| -``` |
| 7 | +Oftentimes your actions need to call `transitionTo` on the router, you |
| 8 | +can't just require your router instance as a module into your actions |
| 9 | +because your routes require views which also require the actions, |
| 10 | +creating a cycle indirectly. |
| 11 | + |
| 12 | +`router.js -> routes.js -> SomeComponent.js -> actions.js -> router.js` |
| 13 | + |
| 14 | +To avoid this, you can do one of two things: |
| 15 | + |
| 16 | +1. Send the component to the action, think of it like `event.target` in |
| 17 | + DOM events if it bothers you. |
| 18 | + |
| 19 | + ```js |
| 20 | + var SomeActionCreators = require('./SomeActionCreators'); |
| 21 | + var Something = React.createClass({ |
| 22 | + mixins: [ Router.Navigation ], |
| 23 | + handleClick () { |
| 24 | + SomeActionCreators.doStuff({ sourceComponent: this }); |
| 25 | + } |
| 26 | + }); |
| 27 | + ``` |
| 28 | + |
| 29 | + and then in `SomeActionCreators.doStuff` call |
| 30 | + `payload.sourceComponent.transitionTo(...)` |
| 31 | + |
| 32 | +2. Use some sort of application container, or module container for the |
| 33 | + router instance. |
| 34 | + |
| 35 | + ```js |
| 36 | + // RouterContainer.js |
| 37 | + var _router = null; |
| 38 | + exports.set(router => _router = router); |
| 39 | + exports.get(() => _router); |
| 40 | + ``` |
| 41 | + |
| 42 | + ```js |
| 43 | + // main bootstrap file, like main.js or whatever |
| 44 | + var RouterContainer = require('./RouterContainer'); |
| 45 | + var routes = require('./routes'); |
| 46 | + RouterContainer.set(Router.create({ routes })); |
| 47 | + ``` |
| 48 | + |
| 49 | + and then in your `ActionCreators.js` |
| 50 | + |
| 51 | + ```js |
| 52 | + var RouterContainer = require('./RouterContainer'); |
| 53 | + exports.doStuff = (payload) => { |
| 54 | + // stuff |
| 55 | + RouterContainer.get().transitionTo(...); |
| 56 | + } |
| 57 | + ``` |
| 58 | + |
| 59 | +Handling route changes as actions |
| 60 | +--------------------------------- |
| 61 | + |
| 62 | +If you'd like to handle route changes as actions, it could look |
| 63 | +something like this: |
17 | 64 |
|
18 | 65 | ```js
|
19 |
| -// SomeActions.js |
20 |
| - |
21 |
| -// and then action creators can require it like other |
22 |
| -// singletons in the app (or if you don't use singletons, |
23 |
| -// do something else with the router you created in |
24 |
| -// router.js) |
25 |
| -var router = require('../router'); |
26 |
| - |
27 |
| -module.exports = { |
28 |
| - doSomeTransitionThing: function () { |
29 |
| - router.transitionTo('somewhere'); |
30 |
| - } |
31 |
| -}; |
| 66 | +Router.run(routes, (Handler, state) => { |
| 67 | + ActionCreators.changeRoute({ Handler, state }); |
| 68 | +}); |
32 | 69 | ```
|
33 | 70 |
|
34 | 71 | ```js
|
35 |
| -// main.js |
36 |
| - |
37 |
| -// finally, run it in your main script |
38 |
| -var React = require('react'); |
39 |
| -var router = require('./router'); |
40 |
| -router.run(function (Handler, state) { |
41 |
| - // you might want to push the state of the router to a |
42 |
| - // store for whatever reason |
43 |
| - RouterActions.routeChange({routerState: state}); |
| 72 | +// ActionCreators.js |
| 73 | +exports.changeRoute = (payload) => { |
| 74 | + var { Handler } = payload; |
44 | 75 | React.render(<Handler/>, document.body);
|
45 |
| -}); |
| 76 | +}; |
46 | 77 | ```
|
47 | 78 |
|
| 79 | +This is not how we use the router with flux, but to each their own. |
| 80 | +
|
0 commit comments