From b5431ab84677d7947aa905420a022e3802b8f563 Mon Sep 17 00:00:00 2001 From: Aamir Afridi Date: Mon, 22 Jun 2015 00:30:55 +0100 Subject: [PATCH] converted https://github.com/aamirafridi/react-flux-simple-app app to a simple todo list to get better understanding of Flux --- src/js/actions/AppActions.js | 10 ++++- src/js/components/app.js | 69 +++++++++++++++++++++++++----- src/js/constants/AppConstants.js | 3 +- src/js/dispatcher/AppDispatcher.js | 39 +++++++++++++---- src/js/stores/AppStore.js | 37 ++++++++++++++-- 5 files changed, 134 insertions(+), 24 deletions(-) diff --git a/src/js/actions/AppActions.js b/src/js/actions/AppActions.js index bc9bc68..b807d1f 100644 --- a/src/js/actions/AppActions.js +++ b/src/js/actions/AppActions.js @@ -6,8 +6,14 @@ var AppActions = { AppDispatcher.handleViewAction({ actionType:AppConstants.ADD_ITEM, item: item - }) + }); + }, + removeItem: function(itemIndex){ + AppDispatcher.handleViewAction({ + actionType:AppConstants.REMOVE_ITEM, + itemIndex: itemIndex + }); } } -module.exports = AppActions +module.exports = AppActions; \ No newline at end of file diff --git a/src/js/components/app.js b/src/js/components/app.js index 8c7fd89..1dd84b6 100644 --- a/src/js/components/app.js +++ b/src/js/components/app.js @@ -3,17 +3,66 @@ var React = require('react'); var AppActions = require('../actions/AppActions'); var AppStore = require('../stores/AppStore'); +var getItemsFromStore = function () { + return { + items: AppStore.getItems() + }; +} + var App = React.createClass({ - handleClick:function(){ - AppActions.addItem('this is the item'); - }, - render:function(){ - return ( -
-

Click this Title, then check console

-
- ) + getInitialState: function() { + return getItemsFromStore(); + }, + + componentDidMount: function() { + AppStore.addChangeListener(this._onChange); + }, + + _onChange: function() { + this.setState(getItemsFromStore()); + }, + + addNewItem: function() { + var newitem = this.refs.taskitem.getDOMNode().value.trim(); + if(newitem.length !== 0) { + AppActions.addItem(newitem); + this.refs.taskitem.getDOMNode().value = ''; + this.refs.taskitem.getDOMNode().focus(); } - }); + else { + console.error('Please enter something. Input is empty'); + } + }, + + removeItem: function(itemIndex) { + AppActions.removeItem(itemIndex); + }, + + render:function(){ + return ( +
+ + +
+
    + { + this.state.items.map(function(item, i) { + var removeItemClick = this.removeItem.bind(this, i); + return ( +
  • + + {item} +
  • + ) + }, this) + } +
+
+
+ ) + } +}); module.exports = App; diff --git a/src/js/constants/AppConstants.js b/src/js/constants/AppConstants.js index 168f529..2a7a8f5 100644 --- a/src/js/constants/AppConstants.js +++ b/src/js/constants/AppConstants.js @@ -1,4 +1,5 @@ module.exports = { ADD_ITEM: 'ADD_ITEM', - REMOVE_ITEM: 'REMOVE_ITEM' + REMOVE_ITEM: 'REMOVE_ITEM', + VIEW_ACTION: 'VIEW_ACTION' }; diff --git a/src/js/dispatcher/AppDispatcher.js b/src/js/dispatcher/AppDispatcher.js index edaf6c1..a361aa9 100644 --- a/src/js/dispatcher/AppDispatcher.js +++ b/src/js/dispatcher/AppDispatcher.js @@ -1,13 +1,36 @@ +/** + * Copyright 2013-2014 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * A singleton that operates as the central hub for application updates. + */ + var Dispatcher = require('flux').Dispatcher; -var assign = require('object-assign'); +var Assign = require('object-assign'); +var AppConstants = require('../constants/AppConstants'); -var AppDispatcher = assign(new Dispatcher(), { - handleViewAction: function(action) { - this.dispatch({ - source: 'VIEW_ACTION', - action: action - }); - } +var AppDispatcher = Assign(new Dispatcher(), { + /** + * @param {object} action The details of the action, including the action's + * type and additional data coming from the view. + */ + handleViewAction: function(action) { + this.dispatch({ + source: AppConstants.VIEW_ACTION, + action: action + }); + } }); module.exports = AppDispatcher; diff --git a/src/js/stores/AppStore.js b/src/js/stores/AppStore.js index 70c2aa0..3571fcc 100644 --- a/src/js/stores/AppStore.js +++ b/src/js/stores/AppStore.js @@ -5,16 +5,47 @@ var assign = require('object-assign'); var CHANGE_EVENT = 'change'; +var items = []; var AppStore = assign({}, EventEmitter.prototype, { + emitChange: function() { this.emit(CHANGE_EVENT); + }, + + addChangeListener: function(callback) { + this.on(CHANGE_EVENT, callback); + }, + + getItems: function() { + return items; + }, + + addItem: function(item) { + if(items.indexOf(item) === -1) { + items.push(item); + } + }, + + removeItem: function(index) { + items.splice(index, 1); } }); -AppDispatcher.register(function(payload){ - console.log(payload); - return true; +AppStore.dispatchToken = AppDispatcher.register(function(payload){ + var action = payload.action; + switch(action.actionType) { + case AppConstants.ADD_ITEM: + AppStore.addItem(action.item); + AppStore.emitChange(); + break; + case AppConstants.REMOVE_ITEM: + AppStore.removeItem(action.itemIndex); + AppStore.emitChange(); + break; + default: + // do nothing + } }); module.exports = AppStore;