

A simpler web architecture using React, Flux, CSP, and FRP concepts - juliangamble
http://codrspace.com/allenkim67/a-simpler-web-architecture-using-flux-csp-and-frp-concepts/

======
staltz
There is absolutely nothing related to FRP in this blog post, not even
"composable event streams" for that matter. This is just using a CSP channel
as a (global) event bus. It essentially replaces the (global) dispatcher with
a CSP channel. This blog post's approach is essentially typical Flux and
nothing else. And doesn't improve to make it more functional either, because
both `onClick={this.clickHandler}` and `yield csp.put(channel, {actionType:
'incr'});` are imperative code.

~~~
mst
Plus both redux and fluctuations work using immutable state and reducers
rather than mutating actions.

------
jarpineh
This looks really fun way to develop React apps.

I just developed a React app, and managed to trip over state related problems
at every stage. First with full state outside components, then within a top
component, then I tried with a simple store type concept. Whenever I had to
deal with async issues, I made a mistake with communicating ongoing state or
getting React to notice changed state. I was waiting for Redux to go 1.0
(which it apparently did yesterday!).

I wonder how async updates, like network requests, to the model should work?
Perhaps two channels, one for events from the components to what ever is
handling requests for you (I just used D3, since I have some other uses for
it), and then it can message the results via channel to what actually updates
the model.

OP's example reminded me strongly of Mithril [1]. Though with addition of CSP
channels to communicate changes, and explicit external render call, which
Mithril allows also, but I don't remember having to use. It's clean and simple
looking, and I like it. Now I got one more way to mess with my app state. And
should I decide to use Mithril again on other projects, CSP seems like a
worthy addition if it can be applied this easy.

[1] [https://lhorie.github.io/mithril/](https://lhorie.github.io/mithril/)

~~~
davexunit
I have a small project that I poke at that uses Mithril + Kefir for a nice
virtual DOM + FRP architecture. A few lines of glue code and I was good to go:
[https://git.dthompson.us/guix-
web.git/blob/HEAD:/js/utils.js...](https://git.dthompson.us/guix-
web.git/blob/HEAD:/js/utils.js#l48)

(pardon the self-signed cert)

~~~
jarpineh
Kefir looks interesting, thanks for the pointer!

Now if somebody makes async channel combinator so that I wouldn't had to build
so much boilerplate for network requests. Be it direct callbacks or promises
or the new fetch specification, control flow of async operations seems to
require more than one channel and glue code in between. That seems to bend the
paradigm a bit too much for what is essentially IO ops in my apps.

------
jergason
This is exactly the Same as Elm, without the type system to help you out.

~~~
erokar
Agree. ReactJS was inspired by Elm as far as I know, Purescript has a
framework purescript-signal that is inspired by Elm, ClojureScript has Zelkova
that is inspired by Elm, and on it goes.

Makes it more and more tempting to just go straigth to the source and simply
use Elm.

~~~
seanmcdirmid
I think React predates Elm, and FRP has been around since 1995. React also
isn't very FRP, it has more of the feeling of an immediate-mode GUI.

~~~
tlrobinson
(FYI Wikipedia says Elm was released in 2012 and React in 2013, but that
doesn't mean Facebook/Instagram weren't working on it before. Also Asana has
been doing similar things since ~2009.

~~~
seanmcdirmid
There isn't much new in React; they just got the timing right and went with a
very solid design that was innovative enough. It really does look a lot like
SOL and other immediate mode UI frameworks, with a touch of optimization for
the web and some better identity management. But I don't get why people call
it FRP though, its notion of components and composition is completely
different from what originated in the original Hudak/Elliott work on Fran with
higher order function compositions over signals (react is much more object
based and much less functional). With Elm, the lineage is obvious, but for
React it just seems like a misapplied label.

~~~
jarpineh
Higher level concepts in area so rife with incidental complexity like
programming tend to get lost in the details of the implementation. Patterns
and abstract concepts like FRP can only be understood by with implementation.
Ideas tend to bend before working code, then again with an example app you
enthusiastically write for your blog, and then again when someone bases her
next project on that (not to mention HN discussions...).

I like to learn thing this way, and not care that much about what the alphabet
soup entails. Try to find what is a proper JavaScript MVC framework. And then
write the first one yourself ;)

I'm currently reading Clojure Reactive Programming, which differentiates from
FRP using another term, CES for Compositional Event Systems, and goes to some
length into history of these concepts, like higher order FRP, First Order FRP,
Arrowized FRP, and of course Observer pattern and Data Flow programming. There
is also Elm's creator's presentation at Strange Loop last year of the same
topic:

[https://www.youtube.com/watch?v=Agu6jipKfYw](https://www.youtube.com/watch?v=Agu6jipKfYw)

~~~
seanmcdirmid
I saw Evan's talk at Splash, and while it was good, I think the history is far
more complex and nuanced than you can fit into a one hour keynote! When I hear
CES I think component-entity systems (also popular in Clojure), but they have
been rebranded as entity component systems (to not conflict with event
systems), while Rx (Erik Meijer) would be more of where compositional event
systems came from.

I have my own system that supports side effects with transactional semantics
(see [http://research.microsoft.com/en-
us/um/people/smcdirm/apx/in...](http://research.microsoft.com/en-
us/um/people/smcdirm/apx/index.html) for the latest). I try to keep my
bibliography straight since the questions will always be asked (how does your
work compare to X?).

------
tlrobinson
I don't know js-csp (I prefer ES7 async/await + promises or streams) so
correct me if I'm wrong, but the "csp.go" here isn't required since it's a
single operation and the return value isn't used:

    
    
        csp.go(function*(){
          yield csp.put(channel, {actionType: 'incr'});
        });
    

I assume it's essentially the same as doing the following using async/await:

    
    
        (async function() {
            await csp.put(...);
        })();
    

Which is pointless.

~~~
idibidiart
I think the idea is to update the model asynchronously via put before
rendering the new state via take. I'm not entirely sure (I don't know csp
much) but I think using a single CSP channel makes that trivial, so you're
always updating before rendering.

Would appreciate more insight and/or correction...

~~~
tlrobinson
Right, but I presume csp.put() is asynchronous already, there's no point in
wrapping it in csp.go().

------
tzaman
The problem is that generators are not that widely supported (yet). You could
replace CSP with something like Bacon.js and likely achieve the same effect
(don't have an example, but I'm researching the area for a new project)

~~~
jevakallio
Take a look at [http://cycle.js.org](http://cycle.js.org) \- it implements
essentially the same concept using RxJS instead of csp and virtual-dom instead
of React.

~~~
stardrive
Except remember, RxJS is also a growing standard and the virtual-DOM Cycle.js
uses has been tested to be a fair amount faster and robust than the one React
has.

Then there is also Cycle's Model-View-Intent pattern and leading edge work on
component integration, which is in line with W3C standards. Cycle's drivers
also allow Cycle.js to integrate or target many options.

Things have been fragmented and Cycle.js seems to have brought the best
together, representing a new and intelligent vortex of progress.

Before I took the time to understand what Cycle.js was about I was naive and
thought React was it. I now understand how poorly it's reactivity has been
implemented. On the other hand Cycle.js is fully reactive and has brought
structure, flow and a sense of intelligence back to my app development.

------
tel
The two challenges past this point are (a) making the components ignorant to
the larger structure of the single state enabling things like component-local
state and state representation independence and (b) getting creative with how
to construct reducers composably so that various domain concerns are separated
from one another in the construction of the core state.

------
geonic
How do you make sure that all your components have access to the same channel?
In a typical setup you'd use something like webpack to import modules from
separate files. Calling var channel = csp.chan() in each of these will create
unique channels, doesn't it? The way I see it you'd need to pass this channel
down to each component.

------
pavlov
Why not have "incr" be a method on the model? Then the update() function with
the big switch on "actionType" could be replaced with:

    
    
        model[action]()

~~~
Retozi
I think this is a bad idea.

First with methods, you have mutable state, which I believe should be avoided.
It causes a lot of problems for efficient rendering.

You could make some kind of wrapper, but I guess it's not worth the hassle to
save a couple of characters.

Second, Action can cause complex writes that touch more than one model (or if
you have one global model, multiple state slices). You probably want to have
the write functions named independently, so they can be reused over multiple
actions if necessary.

~~~
pavlov
You don't avoid mutable state by doing "model.count += 1" in a separate
update() function rather than a method on the model.

Both are functions that operate on the same data; the OO syntax is just a
convenience that was invented exactly for the reason of avoiding endless
switch statements in dispatching actions on a particular piece of data.

~~~
danielmason
Doesn't the OO approach just move the work of the switch statement into the
class declaration of the model? In practice, OO is about encapsulation, and FP
is not. So it's probably not too surprising that the author chose not mix
metaphors.

This is also modeled after an architecture in a statically typed language that
expresses possible actions as a single union type, in which every possible
type must be handled. There's no similar compile-time guarantee in JS, but a
switch statements with constants is a reasonable approximation of the idea.

------
fleshshelf
It probably won't scale well due to the number of ddp connections required,
but I'm using Meteor and React for a side project. It's very pleasant to work
with.

------
slake
How does this scale to multiple views, models, etc?

