Skip to content

Instantly share code, notes, and snippets.

@gaearon
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gaearon/3a3bfe0b8191cb3abcd7 to your computer and use it in GitHub Desktop.
Save gaearon/3a3bfe0b8191cb3abcd7 to your computer and use it in GitHub Desktop.
Removing duplication from similar paginating Flux Stores
// Assumes you're using normalizr https://github.com/gaearon/normalizr
// ---------------
// Helpers:
// ---------------
// StoreUtils
'use strict';
var EventEmitter = require('events').EventEmitter,
merge = require('react/lib/merge'),
CHANGE_EVENT = 'change';
var StoreUtils = {
createStore(spec) {
var store = merge(EventEmitter.prototype, merge(spec, {
emitChange() {
this.emit(CHANGE_EVENT);
},
addChangeListener(callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener(callback) {
this.removeListener(CHANGE_EVENT, callback);
}
}));
store.setMaxListeners(0);
return store;
}
};
module.exports = StoreUtils;
// PaginatedList.js
'use strict';
var _ = require('underscore'),
invariant = require('react/lib/invariant');
class PaginatedList {
constructor(items) {
this._items = items || [];
this._pageCount = 0;
this._isExpectingPage = false;
}
getAll() {
return this._items;
}
getPageCount() {
return this._pageCount;
}
isExpectingPage() {
return this._isExpectingPage;
}
expectPage() {
invariant(!this._isExpectingPage, 'Cannot call expectPage twice without prior cancelPage or receivePage call.');
this._isExpectingPage = true;
}
cancelPage() {
invariant(this._isExpectingPage, 'Cannot call cancelPage without prior expectPage call.');
this._isExpectingPage = false;
}
receivePage(newItems) {
invariant(this._isExpectingPage, 'Cannot call receivePage without prior expectPage call.');
if (newItems.length) {
this._items = _.union(this._items, newItems);
}
this._isExpectingPage = false;
this._pageCount++;
}
}
module.exports = PaginatedList;
// PaginatedStoreUtils.js
'use strict';
var StoreUtils = require('./store_utils'),
StampStore = require('stores/stamp_store'),
UserStore = require('stores/user_store'),
ZineStore = require('stores/zine_store'),
AppDispatcher = require('dispatcher/app_dispatcher'),
PaginatedList = require('utils/paginated_list'),
invariant = require('react/lib/invariant'),
createStore = StoreUtils.createStore;
var CONTENT_STORES = [
StampStore.dispatchToken,
UserStore.dispatchToken,
ZineStore.dispatchToken
];
var PaginatedStoreUtils = {
createPaginatedStore({
request: requestAction,
error: errorAction,
success: successAction
}) {
invariant(requestAction, 'Pass a valid request action.');
invariant(errorAction, 'Pass a valid error action.');
invariant(successAction, 'Pass a valid success action.');
var list = new PaginatedList(),
store,
handler;
store = createStore({
getAll() {
return list.getAll();
},
getPageCount() {
return list.getPageCount();
},
isFetching() {
return list.isExpectingPage();
}
});
handler = function (payload) {
var action = payload.action;
switch (action.type) {
case requestAction:
list.expectPage();
break;
case errorAction:
list.cancelPage();
break;
case successAction:
AppDispatcher.waitFor(CONTENT_STORES);
list.receivePage(action.response.result.objects);
break;
}
store.emitChange();
};
return {
store: store,
handler: handler
};
},
};
module.exports = PaginatedStoreUtils;
// ---------------
// Usage:
// ---------------
// FeedStampStore.js
'use strict';
var AppDispatcher = require('../dispatcher/app_dispatcher'),
AppConstants = require('../constants/app_constants'),
PaginatedStoreUtils = require('utils/paginated_store_utils'),
createPaginatedStore = PaginatedStoreUtils.createPaginatedStore,
ActionTypes = AppConstants.ActionTypes;
var actions = {
request: ActionTypes.REQUEST_FEED_STAMPS,
error: ActionTypes.HANDLE_FEED_STAMPS_ERROR,
success: ActionTypes.RECEIVE_FEED_STAMPS
};
var {
store: FeedStampStore,
handler
} = createPaginatedStore(actions);
AppDispatcher.register(handler);
module.exports = FeedStampStore;
// AboutZineStore.js
'use strict';
var AppDispatcher = require('../dispatcher/app_dispatcher'),
AppConstants = require('../constants/app_constants'),
PaginatedStoreUtils = require('utils/paginated_store_utils'),
createPaginatedStore = PaginatedStoreUtils.createPaginatedStore,
ActionTypes = AppConstants.ActionTypes;
var actions = {
request: ActionTypes.REQUEST_ABOUT_ZINES,
error: ActionTypes.HANDLE_ABOUT_ZINES_ERROR,
success: ActionTypes.RECEIVE_ABOUT_ZINES
};
var {
store: AboutZineStore,
handler
} = createPaginatedStore(actions);
AppDispatcher.register(handler);
module.exports = AboutZineStore;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment