Federal

Minimalistic centralized React store

Federal wraps your react components, creating a centralized data store. It's similar to Redux, in a lot of ways.

Redux is great, and is often the right choice. But, sometimes it adds too much complexity to set up a simple page; As in their todo list example, there's a main index.js , actions/index.js , reducers/todo.js , reducers/visibilityFilter.js , reducers/index.js , and finally the presentation components. All for a simple todo.

Federal takes the 'less is more' approach. In any file that uses Federal, you simply need to provide an intial store object, and an object of actions (e.g. actions/index.js ). Then, you can connect() any component to the store, which will result in it receiving store .props , including .props.dispatch for each action method (e.g. this.props.dispatch.setStatus('status') ).

Can I use this in Production?

Of course! It's currently being used, in production, on Conjure.

Setup

npm install --save federal

Use

Simple Example

This example uses Federal to wrap a page content with a centralized store, and then has a child component ( <Header /> ) connect to the store, which allows it to render the user's name.

import Federal from ' federal ' ; import Header from ' ../../components/Header ' ; export default ( { account } ) => { const initialStore = { account } ; return ( < Federal store = { initialStore } > < Header /> </ Federal > ) ; } ;

import { connect } from ' federal ' ; const Header = ( { account } ) => ( < header > < dl > < dt > User </ dt > < dd > { account . name } </ dd > </ dl > </ header > ) ; export default connect ( ) ( Header ) ;

Selectors

Let's say the above example's initialStore changes to something like this:

const initialStore = { account , products , notices } ;

In this case, you don't want or need products or notices in order to render <Header /> . You can use a selector to minimize the scope of the store changes passed to a component. Selectors are passed to connect() .

const selector = store => ( { account : store . account } ) ; export default connect ( selector ) ( Header ) ;

Actions

Adding actions allows you to dispatch a change to the central store. A dispatch will then ripple and update to any subscribed components.

Actions must return a new object, or Federal will consider nothing to have changed.

import Federal from ' federal ' ; import CountSummary from ' ../../components/CountSummary ' ; import CountInteractions from ' ../../components/CountInteractions ' import actions from ' ./actions ' ; export default ( ) => { const initialStore = { count : 0 } ; return ( < Federal store = { initialStore } actions = { actions } > < CountSummary /> < CountInteractions /> </ Federal > ) ; } ;

const resetCount = store => { return Object . assign ( { } , store , { count : 0 } ) ; } ; const addToCount = ( store , { addition } ) => { return Object . assign ( { } , store , { count : store . count + addition } ) ; } ; export default { resetCount , addToCount } ;

import { connect } from ' federal ' ; const CountSummary = ( { count } ) => ( < div > Current count is { count } </ div > ) ; export default connect ( ) ( CountSummary ) ;

import { connect } from ' federal ' ; const CountInteractions = ( { dispatch } ) => ( < div > < div > < button type = ' button ' onClick = { ( ) => { dispatch . addToCount ( { addition : 1 } ) ; } } > increment count </ button > </ div > < div > < button type = ' button ' onClick = { ( ) => { dispatch . resetCount ( ) ; } } > reset count </ button > </ div > </ div > ) ; export default connect ( ) ( CountInteractions ) ;

Action Callbacks

Actions have an optional callback.

dispatch . addToCount ( { addition : 1 } , ( ) => { } ) ;

Actions via connect()

A component may have local actions, while <Federal> is rendered at a different level in the layout. You can append action handlers to the connected components.