component

The component module exports a factory method, providing a declarative way of generating Kefir.Observables to manage the application UI lifecycle. They are designed to mount an already rendered DOM, with the server providing the DOM and a Kefir.Observable of component props.

component factories can be composed of several Kefir.Observable-returning functions, described below, which form a Kefir.Observable-returning function of its own. Each of these configuration options are optional. A component that doesn’t do anything may not be particularly useful, but it is valid.

Word of Warning

The implementation details for these functions are subject change. It is recommended to use the brookjs modules to describe the component lifecycle, as these will be updated along with the implementation details. The long-term goal is to develop these modules for stability & stand-alone use, but right now, the component and the dependent modules are coupled to one another. Use these tools accordingly.

component will eventually act as a compile target for a Handlebars-based tagged template function, which will provide a JSX-like syntax for declaring components while providing hooks for deep control over the component lifecycle and behavior.

How to Use

A component factory function is generated by passing an configuration object into the factory method.

// dummy.js
import { component } from 'brookjs';
import Kefir from 'kefir';

const events = el => Kefir.fromEvents(el, 'click')
    .map(() => ({ type: 'COMPONENT_CLICK' }));

const render = (el, props, update) => Kefir.stream(emitter => {
   let loop = requestAnimationFrame(() => {
       el.disabled = update.disabled;

       emitter.end();
   });

   return () => cancelAnimationFrame(loop);
});

export default component({ events, render });

Somewhere else, mount the component to its element and subscribe to its actions:

// app.js
import DummyComponent from './dummy';

const { __INITIAL_STATE__ } = global;

const app = DummyComponent(el.getElementById('app'), __INITIAL_STATE__);

let sub = app.observe({ value: action => console.log(action)});

Each of these configuration options have an associated brookjs module, which exports a factory method for generating these functions from a configuration.

Configuration Object

The configuration object defines the behavior of the component over its lifecycle. All stream generating functions provide ways of emitting values into the component stream. All of the properties of the configuration object are optional.

Note: All functions must be curried. brookjs relies on ramda for functional programming helpers, and highly recommends using the same. Use babel-plugin-ramda to ensure the smallest possible build.

  • {Function} events - events$ stream returning function. Called with the element and should return a stream of events from the DOM. The top level element will not change during the lifecycle of the component, but any underlying element can, so any custom event implementation should use event delegation.
    • Parameters:
      • {Element} el - Component element.
    • Returns:
      • {Kefir.Observable} Observable of events from the element.
  • {Function} render - render$ stream returning function. Called with the component element el and the props$ stream.
    • Parameters:
      • {Element} el - Component element.
      • {Kefir.Observable<props>} props$ - Previous component props.
    • Returns:
      • {Kefir.Observable} Observable of renders from the element. Should emit no actions.
  • {Function} children - children$ stream returning function. Called once, when the component is mounted, passing the component element el.
    • Parameters:
      • {Element} el - Component element.
      • {Kefir.Observable} props$ - Observable of props. Used to render children.
    • Returns:
      • {Kefir.Observable} Observable of events from the children. Does not need to end.
  • {Function} combinator - Hook to combine streams before returning them from the factory. Merges the streams by default.
    • Paramters:
      • {Object} streams - Object containing a property for each component stream, including events$, render$, children$, and onMount$. Should return a new stream combining the provided events. Provides a hook to coordinate stream events, if necessary.
  • {Function} onMount - onMount$ stream returning function. Called once, when the component is mounted, providing an entry point for any custom event or render logic.
    • Parameters:
      • {Element} el - Componenent element.
      • {Kefir.Observable} props$ - Observable of props. Used to render children.
    • Returns:
      • {Kefir.Observable} - Observable of events from the component.
  • {Function} shouldUpdate - Determines whether to re-render the element. Called with the previous and next props, returning a boolean indicating whether the component should re-render. Returns true be default.
    • Parameters:
      • {Object} prev - Previous props.
      • {Object} next - Next props.
    • Returns:
      • {boolean} Whether the component should re-render.