Socket
Socket
Sign inDemoInstall

flax

Package Overview
Dependencies
23
Maintainers
2
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    flax

A productive flux implementation to be used with ReactJS


Version published
Weekly downloads
13
increased by18.18%
Maintainers
2
Install size
3.05 MB
Created
Weekly downloads
 

Readme

Source

Flax

A productive flux implementation to be used with ReactJS

Flax is based on Flux

Goals

  • Productivity, objectivity and clarity
  • Maintain as much freedom as traditional Flux
  • Common flux problems solution proposals

Why Flax?

Flax is being developed to address professional level challenges with:

  • Clarity: Flax lets you write Flux in a similar way you would write an app with ReactJS, making it intuitive to learn;
  • Productivity: Flax reduces the common boilerplate while not losing granularity such as the publish-subscribe stores' pattern, but still making simpler syntax possible;
  • Seamlessness: with Flax, for instance, there is little difference between sync and async actions, making action creators easy to implement without additional middleware;
  • Pattern-oriented: alongside with the docs, this repository is being built to also show the best unidirectional dataflow practices to be used with Flax;
  • Developer tools: Flax is being designed to support the creation of user-defined development tools. See flax-devtools, as an example;

Usage

Actions

import Flax from 'flax';

const AppActions = Flax.createActionCreator({
  displayName: 'AppActions',

  // Action with empty payload
  action1() {
    // ...
    this.dispatch();
  },
  
  // Action with some payload
  action2(x, y) {
    x++;
    y++;
    this.dispatch({x, y});
  },
  
  // Async action
  
  /*
  *  We suggest all async requests to be done inside action creators as a form of keeping the stores sync
  */
  action3(x) {
    this.dispatch({loading: true});
    fecth('<url>').then(response => {
      let data = response.json() + x;
      this.dispatch({
        loading: false,
        data
      });
      this.resolve(); // action finished successful
    }).catch(err => {
      this.dispatch({
        loading: false,
        err
      });
      this.reject(); // action finished with failure
    });
  }
});

export default AppActions;

Stores

import Flax from 'flax';
import AppActions from '../actions/AppActions.jsx';

const AppStore = Flax.createStore({
  displayName: 'AppStore',

  getInitialState() {
    return {
      num1: 0,
      num2: 0,
      loading: false,
      error: null
    };
  },

  getActionBinds() {
    return [
      [AppActions.action1, this._handleAction1],
      [AppActions.action2, this._handleAction2],
      [AppActions.action3, this._handleAction3]
    ];
  },

  events: {
    NUM1: null,
    NUM2: null,
    LOADING: null,
    ERROR: null
  },

  _handleAction1() {
    this.state.num1 = 0;
    this.state.num2 = 0;
    this.emitChange(this.NUM1);
    this.emitChange(this.NUM2);
  },

  _handleAction2(payload) {
    this.state.num1 = payload.x;
    this.state.num2 = payload.y;
    this.emitChange(this.NUM1);
    this.emitChange(this.NUM2);
  },

  _handleAction3({loading, data, err}) {
    this.state.loading = false;
    if (err) return this.emitChange(this.ERROR);
    if (loading) {
      this.state.loading = true;
      this.emitChange(this.LOADING);
    } else {
      this.state.num1 = data;
      this.emitChange(this.NUM1);
    }
  },

  getters: {
    getNum1() {
      return this.state.num1;
    },

    getNum2() {
      return this.state.num2;
    },

    getLoading() {
      return this.state.loading;
    },

    getError() {
      return this.state.error;
    }
  }
  
});

export default AppStore;

View Controller

import React from 'react';
import AppActions from '../actions/AppActions.jsx';
import AppStore from '../stores/AppStore.js';

import {
  StoreWatcher
} from 'flax';

const App = React.createClass({
  mixins: [StoreWatcher],

  getEventBinds() {
    return [
      [AppStore.NUM1, this._handleNum1],
      [AppStore.NUM2, this._handleNum2],
      [AppStore.LOADING, this._handleLoading],
      [AppStore.ERROR, this._handleError]
    ];
  },

  getInitialState() {
    return {
      num1: AppStore.getNum1(),
      num2: AppStore.getNum2(),
      loading: AppStore.getLoading(),
      error: AppStore.getError()
    };
  },

  _handleNum1() {
    this.setState({
      num1: AppStore.getNum1()
    });
  },

  _handleNum2() {
    this.setState({
      num2: AppStore.getNum2()
    });
  },

  _handleLoading() {
    this.setState({
      loading: AppStore.getLoading()
    });
  },

  _handleError() {
    this.setState({
      error: AppStore.getError()
    });
  },

  _handleAction1() {
    AppActions.action1();
  },

  _handleAction2() {
    AppActions.action2(1, 2);
  },

  _handleAction3() {
    // Action chaining is important to wait for async action
    AppActions.action3(10).then(() => {
      AppActions.action1();
      AppActions.action2(-1, -2);
    }).catch(() => {
      AppActions.action2(0, 0);
    });
  },

  render() {
    let {num1, num2, loading, error} = this.state;
    
    return (
      <div>
        {loading ? <p>Loading...</p> : null}
        {error ? <p>{error}</p> : null}
        <button onClick={this._handleAction1}>Action1</button>
        <button onClick={this._handleAction2}>Action2</button>
        <button onClick={this._handleAction3}>Action3</button>
        <p>{num1}</p>
        <p>{num2}</p>
      </div>
    );
  }
});

export default App;

getInitialState could be:

getInitialState() {
  let {num1, num2, loading, error} = AppStore.getState();
  return {num1, num2, loading, error};
},

Or in a cleaner code:

getInitialState() {
  return AppStore.getState();
},

If you want less granularity, the component could be set to listen to all AppStore's events:

getEventBinds() {
  return [
    [AppStore.DEFAULT, this._handleAppChange]
  ];
},

And the store event handles:

_handleAppChange() {
  this.setState(AppStore.getState());
},

License

MIT

Contributors

Keywords

FAQs

Last updated on 24 Aug 2016

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc