├── .gitignore
├── README.md
├── app
├── AppDispatcher.js
├── actions
│ └── ExampleActions.es6.js
├── components
│ ├── Application.jsx
│ └── SubComponent.jsx
├── constants
│ └── ExampleConstants.js
└── stores
│ ├── BaseStore.es6.js
│ └── ExampleStore.es6.js
├── package.json
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.orig
2 |
3 | # Mac Finder files
4 | .DS_Store
5 | ._.DS_Store
6 |
7 | # vim
8 | *.swp
9 |
10 | # Dependency detritus
11 | node_modules
12 |
13 | # WebStorm
14 | .idea/
15 |
16 | # Compiled webpack bundles
17 | bundle.js
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | To Start:
2 | ```
3 | npm install
4 | npm start
5 | open localhost:8080/webpack-dev-server/bundle
6 | ```
--------------------------------------------------------------------------------
/app/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | var Dispatcher = require('flux/lib/Dispatcher');
2 |
3 | var copyProperties = require('react/lib/copyProperties');
4 |
5 | var AppDispatcher = copyProperties(new Dispatcher(), {
6 |
7 | /**
8 | * A bridge function between the views and the dispatcher, marking the action
9 | * as a view action. Another variant here could be handleServerAction.
10 | * @param {object} action The data coming from the view.
11 | */
12 | handleViewAction: function(action) {
13 | this.dispatch({
14 | source: 'VIEW_ACTION',
15 | action: action
16 | });
17 | }
18 |
19 | });
20 |
21 | module.exports = AppDispatcher;
--------------------------------------------------------------------------------
/app/actions/ExampleActions.es6.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../AppDispatcher');
2 | var ExampleConstants = require('constants/ExampleConstants');
3 |
4 | var ExampleActions = {
5 |
6 | sendMessage : message => {
7 | AppDispatcher.handleViewAction({
8 | actionType : ExampleConstants.SEND_MESSAGE,
9 | message : message
10 | });
11 | }
12 |
13 | };
14 |
15 | module.exports = ExampleActions;
--------------------------------------------------------------------------------
/app/components/Application.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 | var ExampleStore = require('stores/ExampleStore');
4 | var ExampleActions = require('actions/ExampleActions');
5 |
6 | var SubComponent = require('./SubComponent');
7 |
8 | var getState = function() {
9 | return {
10 | message : ExampleStore.message
11 | };
12 | };
13 |
14 | var counter = 0;
15 |
16 | var Application = React.createClass({
17 |
18 | getInitialState : function() {
19 | return getState();
20 | },
21 |
22 | componentDidMount : function() {
23 | ExampleStore.addChangeListener(this._onChange);
24 | },
25 |
26 | componentWillUnmount : function() {
27 | ExampleStore.removeChangeListener(this._onChange);
28 | },
29 |
30 | _onChange : function() {
31 | this.setState(getState());
32 | },
33 |
34 | _sendMessage : function() {
35 | ExampleActions.sendMessage('hello world! ' + counter++);
36 | },
37 |
38 | render : function() {
39 | return (
40 |
41 |
Hello World!
42 | You can edit stuff in here and it will hot update
43 |
44 |
45 |
46 |
47 | );
48 | }
49 |
50 | });
51 |
52 | React.renderComponent(Application(), document.body);
--------------------------------------------------------------------------------
/app/components/SubComponent.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 | var SubComponent = React.createClass({
4 |
5 | render : function() {
6 | return (
7 |
8 |
SUB COMPONENT!
9 | Message : {this.props.message}
10 |
11 | );
12 | }
13 |
14 | });
15 |
16 | module.exports = SubComponent;
--------------------------------------------------------------------------------
/app/constants/ExampleConstants.js:
--------------------------------------------------------------------------------
1 | var keyMirror = require('react/lib/keyMirror');
2 |
3 | module.exports = keyMirror({
4 | SEND_MESSAGE : null
5 | });
--------------------------------------------------------------------------------
/app/stores/BaseStore.es6.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 |
3 | var AppDispatcher = require('../AppDispatcher');
4 | var EventEmitter = require('events').EventEmitter;
5 | var copyProperties = require('react/lib/copyProperties');
6 |
7 | var CHANGE_EVENT = 'change';
8 |
9 |
10 | class BaseStore {
11 |
12 | constructor(actions) {
13 | if (!_.isObject(actions)) {
14 | return;
15 | }
16 |
17 | // Register to handle all updates
18 | AppDispatcher.register(function(payload) {
19 | var action = payload.action;
20 | var text;
21 |
22 | if (actions[action.actionType]) {
23 | actions[action.actionType](action);
24 | }
25 |
26 | return true; // No errors. Needed by promise in Dispatcher.
27 | });
28 | }
29 |
30 | emitChange() {
31 | this.emit(CHANGE_EVENT);
32 | }
33 |
34 | /**
35 | * @param {function} callback
36 | */
37 | addChangeListener(callback) {
38 | this.on(CHANGE_EVENT, callback);
39 | }
40 |
41 | /**
42 | * @param {function} callback
43 | */
44 | removeChangeListener(callback) {
45 | this.removeListener(CHANGE_EVENT, callback);
46 | }
47 | }
48 |
49 | copyProperties(BaseStore.prototype, EventEmitter.prototype);
50 |
51 |
52 | module.exports = BaseStore;
--------------------------------------------------------------------------------
/app/stores/ExampleStore.es6.js:
--------------------------------------------------------------------------------
1 | var BaseStore = require('./BaseStore');
2 | var ExampleConstants = require('constants/ExampleConstants');
3 |
4 | var storeInstance;
5 |
6 | var message = '';
7 |
8 | class ExampleStore extends BaseStore {
9 | get message() {
10 | return message;
11 | }
12 | }
13 |
14 | var actions = {};
15 |
16 | actions[ExampleConstants.SEND_MESSAGE] = action => {
17 | message = action.message;
18 | storeInstance.emitChange();
19 | };
20 |
21 | storeInstance = new ExampleStore(actions);
22 |
23 | module.exports = storeInstance;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-workshop-boilerplate",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "start": "node node_modules/webpack-dev-server/bin/webpack-dev-server.js --hot"
6 | },
7 | "devDependencies": {
8 | "es6-loader": "^0.2.0",
9 | "jsx-loader": "^0.11.0",
10 | "webpack": "^1.3.2-beta9",
11 | "webpack-dev-middleware": "^1.0.10",
12 | "webpack-dev-server": "~1.4.7",
13 | "less": "~1.7.5",
14 | "less-loader": "~0.7.7",
15 | "style-loader": "~0.8.0",
16 | "css-loader": "~0.9.0",
17 | "file-loader": "~0.7.2",
18 | "autoprefixer-loader": "~1.0.0",
19 | "react-hot-loader": "^0.4.5"
20 | },
21 | "dependencies": {
22 | "flux": "^2.0.0",
23 | "react": "^0.11.1",
24 | "lodash": "^2.4.1"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 |
3 | module.exports = {
4 | context : __dirname,
5 | entry : [
6 | 'webpack/hot/dev-server',
7 | './app/components/Application'
8 | ],
9 | output : {
10 | path: __dirname,
11 | filename: 'bundle.js'
12 | },
13 | plugins: [
14 | new webpack.HotModuleReplacementPlugin(),
15 | new webpack.NoErrorsPlugin()
16 | ],
17 | module: {
18 | loaders: [
19 | {test: /\.jsx$/, loaders: ['react-hot', 'jsx-loader?harmony&insertPragma=React.DOM']},
20 | {test: /\.es6\.js$/, loader: 'es6-loader'},
21 |
22 | // compile and include less files
23 | {test: /\.less$/, loader: 'style-loader!css-loader!autoprefixer-loader!less-loader'},
24 |
25 | // allow less files to load urls pointing to font assets
26 | // @TODO: figure out why this is necessary and do it better
27 | {test: /\.(woff|ttf|eot|svg)$/, loader: 'file-loader' }
28 | ]
29 | },
30 | resolve : {
31 | extensions: ['', '.js', '.es6.js', '.jsx'],
32 | alias : {
33 | actions : __dirname + '/app/actions',
34 | constants : __dirname + '/app/constants',
35 | stores : __dirname + '/app/stores'
36 | }
37 | }
38 | };
--------------------------------------------------------------------------------