retroflux

0.2.1 • Public • Published

Retroflux

Build Status npm version Coverage Status devDependency Status

A minimalistic Flux implementation to use with React that allows you to build modular apps. It does not need a "dispatcher" and does not have any other dependencies. Retroflux only provides a mechanism to create stores and create "smart" components that will listen to the stores. Any other implementation details are up to you.

Installation

Install with npm:

npm install --save retroflux

Usage

Retroflux has provides a Store and a Smart component.

Creating a Store

A store consists of accessor and mutator methods. These methods are passed into the store creator. The first argument of the Store is an object that contains the accessor methods. Accesor methods should only read the store's data. The second argument is an object with mutator methods. These methods modify the store's data and will automatically trigger listening smart components to update.

A store can be created as following:

// CounterStore.js
 
import { Store } from 'retroflux';
 
let count = 0;
 
export default Store({
    // accessor methods
    getCount () {
        return count;
    }
}, {
    // mutator methods
    increment () {
        count += 1;
    }
});

Creating actions

In the Flux architecture Actions should trigger Store changes. In the case of Retroflux, actions should simply call the mutator methods of a store. Retroflux itself does not take care of actions. In fact, actions are not even necessary, you could choose to call the store mutators directly. How you implement actions and in what way they are called, is up to you.

Here is an example of an action:

// CounterActions.js
 
import CounterStore from './CounterStore';
 
export default {
    incrementCounter () {
        CounterStore.increment();
    }
};

Creating a Smart component

Smart components listen to one or multiple stores. A smart component should have an update method. This method is called when one of the stores changes. Inside this update method setState can be called, so React will re-render the component. The smart component creator's first argument is basically an object that you would normally pass in to React.createClass (for use with ES6 classes, see below). The remaining arguments are stores that the component should listen to.

A smart component that listens to a store can be created as following:

// CounterComponent.js
 
import React from 'react';
import { Smart } from 'retroflux';
import CounterStore from './CounterStore';
import CounterActions from './CounterActions';
 
export default React.createClass(Smart(
    getInitialState () {
        return {
            count: CounterStore.getCount()
        };
    },
 
    // This method is called when the store(s) update.
    update () {
        this.setState({
            count: CounterStore.getCount()
        });
    },
 
    handleIncrementClick () {
        // Call the increment action
        CounterActions.increment();
    },
 
    render () {
        return (
            <div>
                <button
                    onClick={ this.handleIncrementClick }
                >Increment</button>
                <div>
                    count: { this.state.count }
                </div>
            </div>
        );
    }
}, CounterStore)) // This component will listen to the CounterStore

You can still use any of React's lifecycle methods on the component.

ES6 classes

Creating a smart component based on an ES6 class is also possible. The update method is automatically binded by Retroflux.

Here is an example:

// CounterComponentES6.js
 
import React from 'react';
import { Smart } from 'retroflux';
import CounterStore from './CounterStore';
 
class Counter extends React.Component {
    constructor (props) {
        super(props);
 
        this.state = {
            count: CounterStore.getCount()
        };
    }
 
    // This method is autobinded by Retroflux
    update () {
        this.setState({
            count: CounterStore.getCount()
        });
    }
 
    render () {
        return (
            <div>something</div>
        );
    }
}
 
export default Smart(Counter, CounterStore);

Modular setup

Retroflux modular setup

Retroflux can be used in a modular Flux application setup. Meaning that you can develop components as separate npm packages. A module can have it's own Actions, Stores or Components that communicate with each other. To access those from outside the module, for example from within your app, you need to export the Actions, Stores or Components through your module's interface.

Example of a module interface:

// index.js
 
// In this case the imported folder have an index.js file that exports an object with all actions.
import Actions from './actions/';
import Components from './components/';
import Stores from './stores/'
 
export default {
    Actions,
    Components,
    Stores
};

If you need to use something from the above module from within your app (or from within another module), you can do the following:

import React from 'react';
import { Components } from 'my-module';
 
// As an example the "Components" object from the module could have a "Counter" component as
// a property
let CounterComponent = Components.Counter;
 
export default React.createClass({
    render () {
        retrun (
            <div>
                <Counter />
            </div>
        );
    }
});

The Counter component in the above example can for example have it's own stores and trigger it's own actions. In this case the Counter component is a Smart component. As you can see in the above example, in your app (or your module) you do not have to worry about the Counter's actions or store(s).

Just like Retroflux itself, an implementation of this modular aproach is up to you. The above is just an example of how to can be made possible.

Examples

Help and contributions

Feel free to open an issue or to make a pull request.

License

MIT

Package Sidebar

Install

npm i retroflux

Weekly Downloads

1

Version

0.2.1

License

MIT

Last publish

Collaborators

  • arjanfrans