We're starting to understand how to use cycle.js. Let's do something more interactive now. Let's create a counter app that has a number here displayed and two buttons -- decrement and increment. Whenever you click on one of those it changes the number.
Let's empty our main here and start clean. We're usually going to start by returning an object of sinks. For the DOM sink we're going to have a stream of one value here. We're going to need a button, a paragraph label, and a div to create the view.
We're going to show first a div that has a button. Let's use here a class name dec for decrement. We're going to give the text content as decrement. Then another button for increment.
Here the text content is increment. Then a paragraph with little label that says the number here. For now we don't actually have the number variable, but we're going to introduce that later.
We can see this being displayed on the DOM, and now we need to handle events coming from the user. First we're going to represent the clicks on the decrement button, we're going to call that decClick stream. We use sources.DOM to select the decrement class which will give us this element. Then we want events of type click.
Now we do something similar for increment, like that. These just give us a stream of click events. From this stream of click events we can actually make a stream of numbers. I'm going to call this dec stream, which represents the decrement button.
For each click we're going to map that click -- we don't care what the value is -- to minus one. That means that each click represents the desire to change the number by minus one. Each click on increment represents our wish to change that number by plus one.
These two will help us make a stream called number stream. We don't know how to create it yet, but let's just imagine we have it available and it looks like this. It starts at zero and whenever we press increment it should change the number to one and increment again. Let's imagine we clicked on decrement, it goes back to one, increment, increment, increment, and etc.
If we have this available we can map each number to the virtual DOM that displays that number, and then we are able to accomplish our app.
The question is, given these two, how do I achieve that? I'm going to make another stream here called delta, which is how much I want to change the number. It is simply the merging of decrement stream with increment stream.
Just to make sure what is this really. Imagine that if we plot this in a marble diagram it would look like this, we have the number minus one over time, and it happens every time the decrement button is clicked. The increment would look something like this every time the increment button is clicked.
Delta would just be a merging of those two streams and it would look like that. It just represents how much we want to change the number by.
We can achieve this stream by simply doing a fold on the delta stream. Fold will take here two arguments, the function describing how to change and the initial value. We know that the initial value should be zero.
Now the question is, how to change? This change will take the previous value and the current number. Now we can do something with those.
I can explain how the fold operator works, is that it has always the idea of state, so it starts with that state being the number zero. Once it sees an event from delta stream such as minus one, it will take that previous number which was zero and combine it with x which is minus one from the delta stream, and create previous plus x.
Now it's going to store that one as the new value internal to fold, and then it repeats this process. Whenever it sees plus one, it will take that value, which was minus one, and do minus one plus this delta. This is how it actually keeps state over time. It's called fold because you can imagine that you're folding this as a piece of paper. Then it can combine values with the past.
Once I run that we see this app and once I click those values are being accumulated inside the fold operation, and it works just like we want it to.
This is actually how you keep state in cycle.js. You use a fold operator to remember previous values and combine them to create the next values.