Cycle’s core abstraction is your application as a pure function
main() where inputs are read effects (sources) from the external world and outputs (sinks) are write effects to affect the external world. These side effects in the external world are managed by drivers: plugins that handle DOM effects, HTTP effects, etc.
The internals of
main() are built using Reactive programming primitives, which maximizes separation of concerns, providing a clean and fully declarative way of organizing your code. The dataflow is plainly visible, making it easy to read and understand the code.
Functional means “clean”, and Reactive means “separated”. Cycle.js apps are made of pure functions, which means you know they simply take inputs and generate outputs, without performing any side effects. The building blocks are reactive streams from libraries like RxJS or xstream, which greatly simplify code related to events, asynchrony, and errors. Structuring the application with streams also separates concerns, because all dynamic updates to a piece of data are co-located and impossible to change from outside. As a result, apps in Cycle are entirely
this-less and have nothing comparable to imperative calls such as
Cycle.js is a framework with very few concepts to learn. The core API has just one function:
Drivers are plugin-like simple functions that take messages from sinks and call imperative functions. All side effects are contained in drivers. This means your application is just a pure function, and it becomes easy to swap drivers around. The community has built drivers for React Native, HTML5 Notification, Socket.io, etc. Sources and sinks can be easily used as Adapters and Ports. This also means testing is mostly a matter of feeding inputs and inspecting the output. No deep mocking needed. Your application is just a pure transformation of data.
In every Cycle.js app, each of the stream declarations is a node in a dataflow graph, and the dependencies between declarations are arrows. This means there is a one-to-one correspondence between your code and minimap-like graph of the dataflow between external inputs and external outputs.
In many frameworks the flow of data is implicit: you need to build a mental model of how data moves around in your app. In Cycle.js, the flow of data is clear by reading your code.
Cycle.js has components, but unlike other frameworks, every single Cycle.js app, no matter how complex, is a function that can be reused in a larger Cycle.js app.
Sources and sinks are the interface between the application and the drivers, but they are also the interface between a child component and its parent. Cycle.js components can be simply GUI widgets like in other frameworks, but they are not limited to GUIs only. You can make Web Audio components, network requests components, and others, since the sources/sinks interface is not exclusive to the DOM.
Got 1 hour and 37 minutes? That is all it takes to learn the essentials of Cycle.js. Watch this free Egghead.io video course given by the creator of Cycle.js. Understand Cycle.js from within by following how it is built from scratch, then learn how to transform your ideas into applications.