sflux v0.1.1
Dispatchr with Flux addons
A Flux dispatcher for applications that run on the server and the client.
The package also contains store skeletons for communicating with RESTfull webservices - e.g. sailsjs.
Installation
npm install --save s-flux
Usage
Creating a service
NOTE: You must create a service ONLY if you want to extend it with additional methods. If the provided methods is enough for your application, jump directly to Creating an action section.
Services are used to communicate with a RESTfull backend (using superagent for requests)
// in /<Flux Folder Name>/UserService.js
// create service for users
import BlueprintService from 'sflux/addons/BlueprintService'
class UserService extends BlueprintService {
constructor() {
super({
resourceName: 'user' // used to compose action constants (eg. USER_CREATE_SUCCESS, USER_UPDATE_ERROR, etc..)
});
}
myCustomServiceMethod(request, payload) {
return new Promise((resolve, reject) => {
request('POST', '/my/endpoint')
.end(this.defaultResponseHandler.bind(this, resolve, reject));
});
}
}
export default UserService;
class UserAction extends BlueprintAction { constructor() { let resourceName = 'user'; // if you have added additional methods to service let apiService = new UserService(); super({ resourceName, // if you have added additional methods to service apiService }); // use the custom created service method // in this case the action constant will be // USER_MYCUSTOMACTION_SUCCESS, USER_MYCUSTOMACTION_ERROR, etc. MyCustomAction(context, payload) { return super.BaseAction('myCustomServiceMethod', context, payload); } } }
export default UserAction;
<br/>
###### Creating a store
```js
// in /<Flux Folder Name>/UserStore.js
// create store for users
import BlueprintStore from 'sflux/addons/BlueprintStore';
class UserStore extends BlueprintStore {
constructor(dispatcher) {
super(dispatcher, {
resourceName: 'user'
});
}
}
UserStore.storeName = 'UserStore';
// should return a map of the following form:
/*
* {
* 'USER_CREATE_SUCCESS': function(storeInstance, payload) {
* let data = payload.res.data,
* imData = immutable.fromJs(data);
*
* let newCollection = storeInstance.entities.push(imData);
* storeInstance.entities = newCollection;
* storeInstance.emitChangeAsync();
* }
* }
*/
UserStore.getHandlers = function() {
let bluePrintHandlers = BlueprintStore.getHandlers();
// blueprintHandlers includes already handlers for: `ResourceName_CREATE_SUCCESS`, `ResourceName_GETBYID_SUCCESS`, `ResourceName_GETBY_SUCCESS`,
// `ResourceName_UPDATE_SUCCESS`, `ResourceName_DELETE_SUCCESS`
// If you want to add your additional actions it is super simple:
blueprintHandlers.USER_MYCUSTOMACTION_SUCCESS = (storeInstance, serverPayload) => {
// voila! your data is in serverPayload;
// we recommend using immutable.js to store this data.
}
return bluePrintHandlers;
}
export default UserStore;
// in /<Flux Folder Name>/index.js
// stores && actions
import UserStore from './UserStore';
import UserActions from './UserActions';
import Dispatchr from 'sflux';
let appDispatcher = new Dispatcher({
config: {
// http calls timeout
TIMEOUT: 20000,
// http calls namespace
API_URL: '/api'
}
});
// and then register stores and actions
appDispatcher.registerStore(UserStore);
appDispatcher.registerActions('UserActions', UserActions);
export default appDispatcher;
expressApp.use((req, res, next) => { let context = appDispatcher.createContext({ req: req }); // render the Application component and pass the context as prop ReactDOM.renderToString(<App context = { context } />); // using the context object now you can call any action you need // Ex in Component`s render() method: let UserActionInstance = context.getActions('UserActions');
UserActionInstance.getById(context, 'user-id-to-fetch-from-server').then(() => {
let imUser = UserStoreInstance.getById('user-id-to-fetch'),
jsonedUser = imUser.toJSON();
// and use it here... but, a simple store listener should be created and update the whole app when stores changes
});
});
<br/>
###### Client side usage example
```js
// in <client entry point>.js
import appDispatcher from 'path/to/fluxFolder';
// on client side, use it plain
let context = appDispatcher.createContext();
// and then pass the context object in your react components (or your framework of choice);
ReactDOM.render(<App context = { context } />);
// and use it
let UserStoreInstance = this.props.context.getStore('UserStore');
let immutableUser = UserStoreInstance.getById('unique-user-id');
immutableUser.get('id'); // user's id
immutableUser.get('name'); // user`s name
// etc.
// or call actions
let UserActionInstance = context.getActions('UserActions');
UserActionInstance.getById(context, 'user-id-to-fetch-from-server').then(() => {
let imUser = UserStoreInstance.getById('user-id-to-fetch'),
jsonedUser = imUser.toJSON();
// and use it here... but, a simple store listener should be created and update the whole app when stores changes
});
UserActionInstance.create({
'firstname': 'Some',
'lastname': 'User'
});
###API
Actions
These methods are available by default through BlueprintAction
class:
.create(contextObject, payloadObject)
.getById(contextObject, uniqueIdString)
.getBy(contextObject, fieldsObject)
.update(contextObject, uniqueIdString, payloadObject)
.delete(contextObject, uniqueIdString)
.find(contextObject, queryObject)
+ more soon ...
Services
When you extend BlueprintService
class your service instance will inherit the following methods
.create(contextObject, payloadObject)
=> will make aPOST
request to /<API_URL>/.getById(contextObject, uniqueIdString)
=> will make aGET
request to /<API_URL>//.getBy(contextObject, fieldsObject)
=> will make aGET
request to /<API_URL>/.update(contextObject, uniqueIdString, payloadObject)
=> will make aPOST
request to /<API_URL>//.delete(contextObject, uniqueIdString)
=> will make aDELETE
request to /<API_URL>//.find(contextObject, queryObject)
=> will make aGET
request to /<API_URL>/?+ more soon ...
Stores
... coming soon
Licence
MIT