Managing multiple component instances with Cycle.js + Most.js

During the last two months I’ve been trying different approaches to Web development from Angular/React stacks and I’ve been totally enraptured by functional/reactive programming. In a flash I found myself comfortable writing Cycle.js components initially with Rx.JS, later with xstream and lastly with Most.js. In this article I’ll show a way (I’m sure it’s not the best, that’s why I’m writing this article, so you can suggest me better ones), to manage multiple component instances using Cycle.js and Most.js. In particular, I’ll focus on the power of the combineArray and chain functions from the Most.Js API.

What are we going to do?

We want to create a page which shows an option selection form letting the user choose how many instances of a component must show. The user must be able to change this number at any time and the component instances must update accordingly (reactively). While this example might seem a bit theoretical I think it actually has a lot of practical applications.

The Component

To keep things simple our component will be an input form whose label updates when the user types; here’s the code:

Not a big deal, just a simple component. We can save this file as src/components/userinput.js

Reusing our component

Now that we have our tiny component we want to reuse it in a page that lets the user decide how many instances of the component will display. Notice that thanks to @cycle/isolate each component instance will act as if it’s the only one around. Let’s start writing our app.js under src/

  1. Let’s first import the necessary libraries + our component under src/components/
import most from 'most'
import Cycle from '@cycle/most-run'
import {makeDOMDriver, label,
div, select, option} from '@cycle/dom'
import UserInput from './components/userinput'

2. Now that we are ready we need a function which, given the number of component instances we want to show and sources as arguments, will return a stream which is the combination of our component instances:

Our function InstancesCombiner takes two arguments: instances, which represents the number of instances we want our function to combine and, of course, sources, we’ll see later how to use this function. All this function does is create an array of component instances:

for (let i = 0; i < instances; i++) {    arrayOfComponents.push(UserInput(sources).DOM)

and combine them together into a single stream to return it:

let combinedStream = most.combineArray(
(...args) => div([...args]), arrayOfComponents)
return combinedStream

the previous line of code is very powerful because it allows you to combine all the streams inside an array into a single one.

Wrapping it all up

Now that we have ComponentCombinator we can finally implement intent, model, view and main functions:

Notice what’s happening inside model.chain: we make a further combination between a stream which renders the necessary HTML for the user to choose the component instances number and a stream which is the combination of the above mentioned instances, thanks to the function we previously wrote.

Notice that instances_number comes from the model:

const model = intent$ => intent$.map(
selection => selection.target.value)
.startWith(1)

So our app is now ready. Here’s the complete app.js file:

Check out this example on Github here

Conclusion:

I’m a total beginner in reactive/functional programming so I’m quite sure there are a lot of more interesting ways to do this, that’s why I look forward your feedback and suggestions. Anyways I’m really enjoying Cycle.js therefore I wanted to share my “experiments” with the readers hoping that more than my experience, my enthusiasm for these technologies will be shared. Thanks for reading.

References:

Get started with reactive/functional programming: click here;

Get started with Cycle.js: click here, video course;

Get started with Most.js: click here