# Flux State

Read about [Flux-Data-Flow](http://facebook.github.io/flux/docs/overview.html)

## Install

```
$ npm install @keystack/fluxstate
```


This library is a Flux state management system intended to be used in react applications.

It does includes three things:

1. An action type helper to generate SUCCESS, FAIL and AFTER versions of action types. (useful for async actions)
2. An observable data store
3. An action creator with promise based async middleware to dispatch actions and handle async operations (namely XHR requests)


## Action Type Generator

`FluxState.createConstants( array=['ACTION_TYPE_1','ACTION_TYPE_2], prefix='DOMAIN' )`

<h5>Usage</h5>

```
const UserConstants = FluxState.createConstants([
  'LOGIN',
  'LOGOUT'
], 'USER');
```

<h5>Result</h5>

```
{
   LOGIN:          'USER_LOGIN',
   LOGIN_SUCCESS:  'USER_LOGIN_SUCCESS',
   LOGIN_FAIL:     'USER_LOGIN_FAIL',
   LOGIN_AFTER:    'USER_LOGIN_AFTER',
   LOGOUT:         'USER_LOGOUT'
}
```

It is also possible to configure constant generation.

```
  FluxState.configs.constants.setSeparator(':');
  FluxState.configs.constants.setSuccessSuffix('OK');
  FluxState.configs.constants.setFailSuffix('ERROR');
  FluxState.configs.constants.setAfterSuffix('DONE');
```

now the previous example will result in:

```
{
   LOGIN:        'USER:LOGIN',
   LOGIN_OK:     'USER:LOGIN:OK',
   LOGIN_ERROR:  'USER:LOGIN:ERROR',
   LOGIN_DONE:   'USER:LOGIN:DONE',
   LOGOUT:       'USER:LOGOUT'
}
```

to go back to default configurations use:

```
FluxState.configs.constants.resetToDefaults();
```

## Action Creator

`FluxState.createActions(actionObject={})`

<h5>Usage</h5>

```
const UserActions = FluxState.createActions({
  login: [UserConstants.LOGIN, function(username, password){
    return ApiUsers.login(username,password)
  }]
});
```

```
UserActions.login({
  username : 'user',
  password : 'pass'
}) 
```

<h5>Result</h5>

  
1. `USER_LOGIN` gets dispatched directly before the passed callback gets executed.
2. The passed callback gets executed.
3. Depending on the result of the action callback, it will either:
	- Dispatch USER_LOGIN_SUCCESS with result of resolved Promise.
	- Dispatch USER_LOGIN_FAIL with result of Rejected Promise or Error.
4. `USER_LOGIN_AFTER` gets dispatched after step 3 
	 `USER_LOGIN_SUCCESS` gets dispatched in two cases:  

`USER_LOGIN_SUCCESS` gets dispatched in two cases:  
  1. The callback returns a value
	2. the callback returns a promise which gets resolved  

`USER_LOGIN_FAIL` gets dispatched in two cases:  
  1. The action callback throws an exception or returns an Error  
  2. It returns a promise which gets rejected  


## Observable Data Store

`FluxState.createStore(mixinObject={},[
	['EVENT_TYPE_CONSTANT',(payload)=>{}]
])`


FluxState.createStore takes two parameters:
	1. A mixin object for the store
	2. An array of action listeners

<h5>Helper Methods</h5>

```
getState()       : returns a shallow copy of the current state
persist(@object) : backs up current state in local storage and merges @object
onChange(@cb)    : attaches a callback to be fired when change is observed
offChange(@cb)   : removes callback (typically used in React.Component.cdum lifecycle hook)
```


<h5>Usage</h5>

```
const UserStore = FluxState.createStore({
  
  getInitialState: function(){
    return {
      isAuth: false,
      data: null,
      isLoggingIn: false,
      error: null
    };
  },
  
  storeDidMount: function(){
    // Gets called when store is ready
  },
  
  isAuth: function(){
    return this.get('isAuth')
  }
  
},[
 
 /**
  * called directly before executing login action
  */

 [UserConstants.LOGIN, function onLogin(){
  this.setState({
    isLoggingIn: true,
    error: null
  });
 }],
 
 /**
  * called if login action was successful
  */

 [UserConstants.LOGIN_SUCCESS, function onLoginSuccess(payload){
  this.setState({
    isAuth: true,
    data: payload
  });
 }],

 /**
  * called if login action failed
  */

 [UserConstants.LOGIN_FAIL, function onloginFail(error){
  this.setState({
    error: error.message
  });
 }]
 
 /**
  * called after login action succeeds or fails
  */

 [UserConstants.LOGIN_AFTER, function onloginAfter(error){
  this.setState({
    isLoggingIn: false
  });
 }]

]);
```


