Skip to content

Instantly share code, notes, and snippets.

@davecranwell
Created May 1, 2015 13:46
Show Gist options
  • Save davecranwell/65c95fb5a6b0364c4925 to your computer and use it in GitHub Desktop.
Save davecranwell/65c95fb5a6b0364c4925 to your computer and use it in GitHub Desktop.
React flux issue
/*
* Copyright (c) 2014-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* TodoActions
*/
var AppDispatcher = require('../dispatcher/Dispatcher');
var AppConstants = require('../constants/AppConstants');
var AppActions = {
/**
* @param {string} text
*/
create: function(text) {
AppDispatcher.dispatch({
actionType: AppConstants.TASK_CREATE,
text: text
});
},
/**
* @param {string} id
*/
start: function(id) {
AppDispatcher.dispatch({
actionType: AppConstants.TASK_START,
id: id
});
},
/**
* @param {string} id
*/
stop: function(id, elapsed) {
AppDispatcher.dispatch({
actionType: AppConstants.TASK_STOP,
id: id,
elapsed: elapsed
});
},
/**
* @param {string} id The ID of the ToDo item
* @param {string} text
*/
updateName: function(id, text) {
AppDispatcher.dispatch({
actionType: AppConstants.TASK_UPDATE_TEXT,
id: id,
text: text
});
},
/**
* @param {string} id
*/
destroy: function(id) {
AppDispatcher.dispatch({
actionType: AppConstants.TASK_DESTROY,
id: id
});
}
};
module.exports = AppActions;
/*
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* TaskStore
*/
var AppDispatcher = require('../dispatcher/Dispatcher');
var EventEmitter = require('events').EventEmitter;
var AppConstants = require('../constants/AppConstants');
var assign = require('object-assign');
var CHANGE_EVENT = 'change';
var START_EVENT = 'start';
var _tasks = {};
/**
* Create a Task item (blank)
* @param {string} text The content of the TODO
*/
function create(text) {
// Hand waving here -- not showing how this interacts with XHR or persistent
// server-side storage.
// Using the current timestamp + random number in place of a real id.
var id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
_tasks[id] = {
id: id,
elapsed: 0,
text: text
};
}
/**
* Update a TODO item.
* @param {string} id
* @param {object} updates An object literal containing only the data to be
* updated.
*/
function update(id, updates) {
_tasks[id] = assign({}, _tasks[id], updates);
}
/**
* Delete a TODO item.
* @param {string} id
*/
function destroy(id) {
delete _tasks[id];
}
var AppStore = assign({}, EventEmitter.prototype, {
/**
* Get the entire collection of Tasks.
* @return {object}
*/
getAllTasks: function() {
return _tasks;
},
emitTaskChange: function() {
this.emit(CHANGE_EVENT);
},
emitTaskStart: function(id) {
this.emit(START_EVENT, id);
},
/**
* @param {function} callback
*/
addTaskChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
/**
* @param {function} callback
*/
removeTaskChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
/**
* @param {function} callback
*/
addTaskStartListener: function(callback) {
this.on(START_EVENT, callback);
},
/**
* @param {function} callback
*/
removeTaskStartListener: function(callback) {
this.removeListener(START_EVENT, callback);
}
});
// Register callback to handle all updates
AppDispatcher.register(function(action) {
var text;
switch(action.actionType) {
case AppConstants.TASK_CREATE:
text = action.text.trim();
if (text !== '') {
create(text);
AppStore.emitTaskChange();
}
break;
case AppConstants.TASK_START:
AppStore.emitTaskStart(action.id);
break;
case AppConstants.TASK_STOP:
update(action.id, {elapsed: action.elapsed});
break;
case AppConstants.TASK_UPDATE_NAME:
text = action.text.trim();
if (text !== '') {
update(action.id, {text: text});
AppStore.emitTaskChange();
}
break;
case AppConstants.TASK_DESTROY:
destroy(action.id);
AppStore.emitTaskChange();
break;
default:
// no op
}
});
module.exports = AppStore;
var React = require('react');
var AppStore = require('../stores/AppStore');
var TextInput = require('./TextInput.jsx');
var AppActions = require('../actions/AppActions.js');
var Task = React.createClass({
getInitialState: function(){
return {
name: "New task",
elapsed: 0,
running: 0,
start: null,
timer: null
}
},
componentDidMount: function() {
AppStore.addTaskStartListener(this._startEventHandler);
this.start();
},
componentWillUnmount: function() {
AppStore.removeTaskStartListener(this._startEventHandler);
},
_startEventHandler: function(id){
console.log('started task', id);
console.log('i am task', this.props.task.id);
// ignore start events from self
if(id != this.props.task.id){
this.stop();
}
},
tick: function(){
this.setState({elapsed: new Date() - this.state.start});
},
toggle: function(e){
if(this.state.running){
this.stop();
}else{
this.start();
}
},
start: function(){
var alreadyElapsed = this.state.elapsed;
this.setState({
running: 1,
start: new Date() - alreadyElapsed,
timer: setInterval(this.tick, 100)
});
console.log('starting task', this.props.task.id)
AppActions.start(this.props.task.id);
},
stop: function(){
clearInterval(this.state.timer);
this.setState({running: 0, timer: null});
console.log('trying to stop', this.props.task.id);
AppActions.stop(this.props.task.id, this.state.elapsed);
},
destroy: function(){
this.stop();
AppActions.destroy(this.props.task.id);
},
updateName: function(e){
var newText = event.target.value.replace(/^\s+|\s+$/g, '')
if(newText.length){
this.setState({name: newText});
}
AppActions.updateName(this.props.task.id, newText);
},
render: function() {
return (
<div>
<TextInput onSave={this.updateName} />
<div onClick={this.toggle}>
<div>id: {this.props.task.id}</div>
<div>name: {this.state.name}</div>
<div>elapsed: {this.state.elapsed}</div>
<div>running: {this.state.running}</div>
</div>
<button onClick={this.destroy}>Delete</button>
</div>
)
}
});
module.exports = Task;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment