Permalink
Browse files

Using routes

  • Loading branch information...
alexishevia committed Nov 27, 2014
1 parent cffce64 commit 29a099f1ea1305cf3ec4d20392907c41fc78aa32
Showing with 278 additions and 9 deletions.
  1. +22 −1 README.md
  2. +16 −0 app.js
  3. +8 −0 components/About.jsx
  4. +14 −1 components/Application.jsx
  5. +8 −0 components/Home.jsx
  6. +12 −0 configs/routes.js
  7. +123 −0 npm-shrinkwrap.json
  8. +4 −1 package.json
  9. +26 −6 server.js
  10. +45 −0 stores/ApplicationStore.js
View
@@ -1,8 +1,29 @@
# Fluxible-App Step by Step
On this post I want to show how to create a fluxible-app step by step. I will be developing one (or several) of Yahoo's [flux examples](https://github.com/yahoo/flux-examples).
On this post I want to show how to create a fluxible app step by step. I will be developing one (or several) of Yahoo's [flux examples](https://github.com/yahoo/flux-examples).
## Hello World
- Install node.js and npm
- package.json with initial dependencies
- create a basic React component that just renders 'Hello World'
- create an express app (server.js). Add a middleware to render our React component.
## Using routes
- Create <Home> and <About> Components
- Modify the ApplicationComponent so it renders either <Home> or <About> based on the current route.
- Create app.js, our Fluxible-app. app.js uses a routrPlugin (with our custom defined routes), and an ApplicationStore, which holds the current route as its state.
- Modify server.js so it creates a new context on each request, and executes the NavigateAction before rendering.
This is the process:
1. A new request is made, server.js receives it.
2. Our middleware creates a new context instance and calls context.executeAction(navigateAction), passing it the current route.
3. NavigateAction uses the routrPlugin to look for a matching route.
3.1 If a match is found, a 'CHANGE_ROUTE_SUCCESS' action is dispatched and the callback is called with no errors.
3.2 If a match is not found, the callback is called with a 'Url does not exist' error.
4. The 'CHANGE_ROUTE_SUCCESS' action is dispatched to all stores registered with the app (ApplicationStore in our case).
Note: A new ApplicationStore instance is created, and the action is immediately dispatched to it.
5. ApplicationStore executes its handleNavigate() method in response to the 'CHANGE_ROUTE_SUCCESS' action. The handleNavigate() method will update the ApplicationStore state.
6. Inside the executeAction callback, we'll create a new instance of our Application component, passing it the current context as a prop. The context, among other things, contains the ApplicationStore instance that was created on step 4.
7. We render the Application component as a string, and send the result as our response.
Since the Application component gets its state from ApplicationStore, and ApplicationStore was updated when it handled the 'CHANGE_ROUTE_SUCCESS', we can use the current state to determine which sub-component to render (<Home> or <About>)
Note: We're using the FluxibleMixin, which includes a handy `getStore()` method that knows how to get the correct store instance from the provided context.
View
16 app.js
@@ -0,0 +1,16 @@
'use strict';
var React = require('react');
var Fluxible = require('fluxible');
var routrPlugin = require('fluxible-plugin-routr');
var app = new Fluxible({
appComponent: React.createFactory(require('./components/Application.jsx'))
});
app.plug(routrPlugin({
routes: require('./configs/routes')
}));
app.registerStore(require('./stores/ApplicationStore'));
module.exports = app;
View
@@ -0,0 +1,8 @@
'use strict';
var React = require('react');
module.exports = React.createClass({
render: function(){
return <div>This is a description of the site.</div>;
}
});
View
@@ -1,8 +1,21 @@
'use strict';
var React = require('react');
var ApplicationStore = require('../stores/ApplicationStore');
var Home = require('./Home.jsx');
var About = require('./About.jsx');
var FluxibleMixin = require('fluxible').Mixin;
var Application = React.createClass({
mixins: [FluxibleMixin],
getInitialState: function () {
return this.getStore(ApplicationStore).getState();
},
render: function(){
return <div>Hello World!</div>;
return (
<div>
{'home' === this.state.currentPageName ? <Home/> : <About/>}
</div>
);
}
});
View
@@ -0,0 +1,8 @@
'use strict';
var React = require('react');
module.exports = React.createClass({
render: function(){
return <div>Welcome to the site!</div>;
}
});
View
@@ -0,0 +1,12 @@
module.exports = {
home: {
path: '/',
method: 'get',
page: 'home'
},
about: {
path: '/about',
method: 'get',
page: 'about'
}
};
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -8,7 +8,10 @@
"dependencies": {
"express": "4.11.2",
"node-jsx": "0.12.4",
"react": "0.12.2"
"react": "0.12.2",
"flux-router-component": "0.4.6",
"fluxible": "0.2.0",
"fluxible-plugin-routr": "0.2.1"
},
"devDependencies": {
"nodemon": "1.3.6"
View
@@ -1,15 +1,35 @@
'use strict';
require('node-jsx').install({ extension: '.jsx' });
var express = require('express');
var server = express();
var port = process.env.PORT || 3000;
require('node-jsx').install({ extension: '.jsx' });
var navigateAction = require('flux-router-component').navigateAction;
var React = require('react');
var AppComponent = React.createFactory(require('./components/Application.jsx'));
var app = require('./app');
server.use(function(req, res, next) {
var component = AppComponent();
var html = React.renderToString(component);
res.send(html);
var context = app.createContext();
context.getActionContext().executeAction(navigateAction, {
path: req.path
}, function (err) {
if (err) {
if (err.status && err.status === 404) {
next();
} else {
next(err);
}
return;
}
var AppComponent = app.getAppComponent();
var component = AppComponent({
context: context.getComponentContext()
});
var html = React.renderToString(component);
res.send(html);
});
});
server.listen(port);
View
@@ -0,0 +1,45 @@
/**
* Copyright 2014, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
var createStore = require('fluxible/utils/createStore');
var ApplicationStore = createStore({
storeName: 'ApplicationStore',
handlers: {
'CHANGE_ROUTE_SUCCESS': 'handleNavigate'
},
initialize: function (dispatcher) {
this.currentPageName = null;
this.currentPage = null;
this.currentRoute = null;
this.pages = require('../configs/routes');
},
handleNavigate: function (route) {
var pageName = route.name;
var page = this.pages[pageName];
if (pageName === this.getCurrentPageName()) {
return;
}
this.currentPageName = pageName;
this.currentPage = page;
this.currentRoute = route;
this.emitChange();
},
getCurrentPageName: function () {
return this.currentPageName;
},
getState: function () {
return {
currentPageName: this.currentPageName,
currentPage: this.currentPage,
pages: this.pages,
route: this.currentRoute
};
}
});
module.exports = ApplicationStore;

0 comments on commit 29a099f

Please sign in to comment.