A simpler web architecture using React, Flux, CSP, and FRP concepts
codrspace.com
codrspace.com
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.
(pardon the self-signed cert)
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.
Makes it more and more tempting to just go straigth to the source and simply use Elm.
Redux was inspired by Elm's update concept, not React.
I was on that train of thought too after using Redux had the side effect of giving me a conceptual understanding of how the update step works in Elm, but I found that "simply" really isn't the right word if your experience is primarily with imperative languages.
e.g. building an app starting from HTML5 history and routing built on top of it is just another API if you already know JavaScript, but it's an entire new set of concepts to learn if you're not au fait with functional programming, as I quickly discovered!
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:
I have my own system that supports side effects with transactional semantics (see http://research.microsoft.com/en-us/um/people/smcdirm/apx/in... for the latest). I try to keep my bibliography straight since the questions will always be asked (how does your work compare to X?).
I am planning to work through the [1] to see if I should switch from the clojure-script/reagent combo on my next side project :)
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.Would appreciate more insight and/or correction...
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.
function gen_f() {
var count = 0;
function f() {
count += 1;
return count;
}
return f;
}
Probably you could use csp.take(channel) like in OP this way, too. I used this solution primarily because I couldn't figure out how generators handle arguments in iteration calls. My problem was to find a string that should be returned for a given index (where there was some complex rules on what string was active when) and to keep looping a list indefinitely. Generators seem to make things syntactically cleaner, but for me at least reasoning about them has been challenging in JS context.Yes, you can replace CSP with Rx style libraries. It's just a different kind of learning curve.
Personally I prefer CSP, as channels are a more primitive approach to writing concurrent applications.
CSP is like a library and Bacon/Rx are like frameworks.
model[action]()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.
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.
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.