0.2.0 • Published 8 years ago

fnux v0.2.0

Weekly downloads
2
License
MIT
Repository
github
Last release
8 years ago

fnux - Functional Flux

Fnux is a Flux framework that allows you to write your UI logic purely functional. This makes your code very easy to test and to reason about. It also helps you to coordinate complex asynchronous operations and gives you control over accessing the global state and triggering side effects.

Fnux runs in the browser as well as on the server. It manages all the UI state within a single Immutable.js Map instance. The different parts of your application can interact with this state via small interfaces. Fnux does not depend on ReactJS but is designed to work well with it.

Installation

$ npm install fnux

Usage example

import createApp from "fnux";
import React from "react";
import ReactDOM from "react-dom";

// a component
const App = React.createClass({
  handleClick() {
    const {invokeIntent} = this.props.context;
    invokeIntent(incrementCounter);
  },

  render: function render() {
    const {queryState} = this.props.context;
    const count = queryState(Counter.getCount);

    return <button onClick={this.handleClick}>You clicked {count} times</button>;
  }
});


// an intent
function incrementCounter(context) {
  const {queryState, updateState} = context;
  const currentCount = queryState(Counter.getCount);
  updateState(Counter.setCount, {count: currentCount + 1});
}


// a store
const Counter = {
  // a query
  getCount(context) {
    // context.state is an immutable.js Map instance
    return context.state.getIn(["counter", "value"]);
  },

  // a transition
  setCount(context, args) {
    return context.state.setIn(["counter", "value"], args.count);
  }
};


// hooking it all together
const app = createApp({
  initialState: {
    counter: {
      value: 0
    }
  }
});

app.subscribe(function render(componentContext) {
  ReactDOM.render(<App context={componentContext} />, document.body);
});
app.triggerUpdate();

API

Fnux distinguishes between components, intents, services and stores that in turn consist of queries and transitions. Components are React components while the other are pure functions that are applied to a context object and an additional data object. The context object provides functions for interactions between the different parts.

Component

Components are plain React components that you can structure to your liking. You don't need any special glue code to connect your components to Fnux. All that Fnux provides is the componentContext containing the functions queryState, valueLink and invokeIntent. It is up to you to pass this object down your component tree. The easiest way to do so is using the context mechanism that React provides. A reference to the componentContext object is passed to the callback function that you pass to subscribe.

componentContext

The componentContext enables components to read data from the state, trigger an intent or connect a form field to a value within the state.

queryState(queryFn, args)

queryState applies queryFn to the queryContext (see below) and the given args object and returns queryFn's return value.

invokeIntent(intentFn, args)

invokeIntent applies intentFn to the intentContext (see below) and the given args object and returns undefined.

valueLink(queryFn, transitionFn)

valueLink returns an object with value and requestChange properties that can be consumed by React's <input /> components (see Two-Way Binding Helpers in the React docs for more details). This allows you to bind a form element to a value within the state without having to write a separate intent function to update the state.

Intent

Intents are functions that collect data via services or queries and generate a new state via transitions. Services might be asynchronous (e.g. when they fetch data over the network) and intents coordinate their results.

Intents are similar to "action creators" in other Flux implementations. The difference is that they don't dispatch action objects but use query and transition functions to interact with the state.

intentContext

The intentContext enables intents to read data from the state, update the state or invoke services.

queryState(queryFn, args)

queryState applies queryFn to the queryContext (see below) and the given args object and returns queryFn's return value.

updateState(transitionFn, args)

updateState applies transitionFn to the transitionContext (see below) and the given args object and returns undefined.

invokeService(serviceFn, args)

invokeService applies serviceFn to the serviceContext (see below) and the given args object and returns the serviceFn's return value.

Service

Services are functions that interact with the "outside world" via the serviceContext. This includes triggering HTTP requests, access sensors such as window.navigator.geolocation but also any client state such as window.location.href or window.innerWidth.

serviceContext

The serviceContext is defined when creating the app object. If you want to allow your services access to the entire global environment then you can simply pass in window:

import createApp from "fnux";
const app = createApp({
  serviceContext: window
});

Alternatively you can restrict the serviceContext to only contain the values and methods that your services need:

import createApp from "fnux";
const app = createApp({
  serviceContext: {
    fetch: window.fetch.bind(window),
    location: window.location,
    viewport: {
      get innerWidth() { return window.innerWidth; },
      get innerHeight() { return window.innerHeight; }
    }
  }
});

Store

Stores bundle functions that either retrieve a value from the state (queries) or return an updated version of the state (transitions). Queries and corresponding transitions should be kept together because it makes it easier to change the structure of the state object during development.

Query

Queries are functions that retrieve a certain value from the state ("getter").

queryContext

The queryContext provides access to the current state object via its state property. This state object is an Immutable.js Map instance.

Transition

Transitions are functions that return an updated version of the state ("setter").

transitionContext

The transitionContext provides access to the current state object via its state property. This state object is an Immutable.js Map instance. The updated state that is returned from the transition function becomes the new state of the app and triggers a re-render of the view.

License

MIT License. See LICENSE.

0.2.0

8 years ago

0.1.2

9 years ago

0.1.1

9 years ago

0.1.0

9 years ago

0.0.1

9 years ago