Fork me on GitHub

I think Redux/Flux-like architecture is a nice way of managing state because it's a very clear way of managing state. Have also been using MobX recently on a new project so we will see how that grows.


Though this is a Clojure forum so I won't talk about MobX too much. I have also tried to use Hoplon in Clojure(script) land, but the HLisp stuff kind of rubs me the wrong way honestly


I think as long as we are discussing state management MobX has to be in the mix. And we are discussing React rather prominently, which will not get converted to CLJS until v42 according to their roadmap. I made that up.


Redux/Flux is clear from 30k feet and next thing you know we are watching 24 free videos and still struggling to do what we want to do. Productivity tools are supposed to save developer energy, not consume it.


Hoplon is great, Matrix is great, binding.scala is great, but MobX is the dataflow mindshare leader. The CLJS community might want to choose carefully in this space.


have you ever built anything with MobX? very tricky to get right. it is very hard to monitor arrays in javascript and requires coding by convention. reagent’s atom system blows mobx out of the water.


also, where did this ‘dataflow’ terminology come from. in my world, this is called the ‘observer pattern’ from the GoF book


Have been using mobx-state-tree/mobx recently and not sure how I feel about it yet. The main positive aspect so far seems to be a lot less boiler plate/things getting in my way. My main concern with it is readability as the code base gets larger + being able to debug/test it (Redux is so easy to debug/test).


Reagent + ratom remains kind of a personal favourite, Re-frame isn't so bad but similar problems to Redux where I feel it gets in my way a lot


Main problem for me is I can never sell Cljs to my team 😛


my memory of mobx is that you can’t observe a blank portion of the state. you can do that with ratoms. i.e. you can create a cursor to something that isn’t there and then you get a re-render when it loads. stuff like that just works better because mobx is kind of a filthy (but awesome) hack


Ah, that may well be true


I think that's the real heart of why ratoms are great, because they are really just a part of the language, they are very idiomatic


MobX feels like it's really pushing JS, and it works really well!


But at the end of the day it is a hack as you say


mobx is also synchronous, if i recall, which is kind of tricky to deal with if you’re not thinking carefully about whether a mutation might cause another mutation


it’s a miracle that mobx works at all 🙂


You could say the same about reagent 🙂


This is true, and why mobx-state-tree/mobx in strict mode forces you to wrap state changes in actions


It's magic written in a language, that compiles to a language, that compiles to a language, that uses magic (react) and compiles to a language and...


CLJS is magic, Reagent is just a nice library 😛


React I think is more a little bloated than magic


Not to mention that the compilation happens on magic written on a language, that compiles to a language, that compiles to a language that...


the distinction for me is that I understand why reagent works: there’s a level of indirection that is built into cljs: specifically the fact that you can only manipulate atoms by derefing them. reagent inserts itself right there in that single place. mobx is doing screwball things to intercept direct object accesses and array manipulations.


sure, Reagent definitely doesn't feel like magic if you know Clojure, it just feels like a natural way of doing things/a slight extension of what you know


Then re-frame is just a pretty opinionated pattern on top of that core


MobX I don't want to the look at the code because I think I'll have nightmares

🙂 4

And I am surprised every time it works, especially in non-strict mode (which I think they have basically acknowledged was a bad idea, though it rules for prototyping)


to be clear: i’m a much stronger js programmer than cljs programmer still. my years of C++ are hard to shake 🙂


If we are surveying the field we are at 30k feet, so I would not exclude any library from discussion over details. If MobX is insufficiently granular, fine. Does it offer anything on transparency? Hoplon/Javen is limited by the “lifting” mechanism. Fine, but is it too great on transparency? Re-frame has a beautifully clear domino thing. Does that mean explicitly coding subscriptions and events? There is no superficial way to explore this space.


ah well that’s the issue. i’m not at 30k feet. I’m building product. everything looks good at 30k feet. 🙂


What are you using now?


And will you use that forever because to survey the choices means stopping typing? 🙂 I understand!


Reagent is great. Keep an eye out for the glitches if you ever see something that makes no sense.


I am as we speak working on a Redux app but dreaming of Reagent

👍 4

i never said anything was excluded or that we shouldn’t talk about it. if i didn’t want to talk about it i wouldn’t be here. i’m interested to hear what milomord and anybody else who actually uses this stuff has to say


i’ve offered my thoughts as to why mobx is hard to use, which came from practical experience


I started with React on a hefty exercise and in two widgets realized why Abramov did Reflux. Re-doing those two widgets with Redux told me how brilliant are the CLJS React wrappers.


I am grateful for the input from a hardcore JSer on MobX. I just surfed the doc and took a deep dive into the internals to explore its solution to glitches, but a real user such as yourself offers great perspective.


I am too early on in my Mobx/Mobx State Tree exploration to offer advice on practical drawbacks/pitfalls unfortunately, but very curious to see how it goes for me


FWIW, I have not yet used it in anger but it feels like React context + suspense attacks the same generic problem as Redux and Reagent (with ratoms) but in a much simpler way


My experience of Reagent/ratoms has been 'joy to work with' pretty much, though it does give maybe too much freedom to me


@milomord be sure to read and understand because you will be bitten by some of that unless you are careful to write code to avoid these pitfalls


esp. suspense I feel like is moving us towards shaking off the "only the V in MVC" lie that we've been using to sell people on React for awhile 😉


Thanks @lee.justin.m, I have already stumbled upon this after being bitten!


It will be interesting to see if people start using Suspense


(outside of presumably FB)


@milomord The True Lisper holds sacred the right to shoot off their own feet with too much freedom.


But I am generally not thrilled with React's own solutions to state management so far


I think they know this hence why they pushed people toward Flux/then Redux and obfuscated the context api somewhat


damn, missed suspense — googling


As I understand Suspense (not that well), it is more about waiting for network requests to complete


it's about any side effects, really


The very best thing in the world is the React doc on context saying “no matter what you do, do not use context”.


AFAICT after 16.3 that's old advice. the new context API has been deemed production ready


the reason that they suggested not to use the old context API was because it was likely to change


honestly I never liked the idea of context within React but I forgave it because it makes some things slightly easier (eg, routers/outside stores)


There was a funny video where someone asked the Facebook team (at an open conference) about context and one of them turned to the others and said, “I told you they would find it.


Haha, context is an escape hatch


most of the uses of state management libs have to do with 2 concerns: 1. plumbing state 2. reacting to side effects context addresses 1. suspense (begins to) address 2


And apparently one we need, in turn a refutation by example of the whole idea of isolation. It’s all connected, spaketh Buddha.


Thing is, I actually think I like React just being the view layer/a declarative view layer


Yeah, and now I see they have some insanely elaborate “forward ref” thingy that let’s us get at the dom.


And if FB are interested in turning it into a more fully fledged framework/standalone solution I will watch with interest but


View and model are one. (Prepare the tar and feathers.)


'View and model are one' such a lisper


I think that declarative and "just being the V" are orthogonal


Actually, I lied. All my views have a value slot. For the model object.


e.g. graphQL + React is declarative, but also quite a bit more than just the V


My guess? They spent three months trying to figure out state management, came up short, and decided to make the gaping whole a feature by bragging about how they were not telling us how to manage state. But we had to use Flux,


I think it's a feature that React has not implemented a lot of what has been filled in by other user-space libraries libs up until now


because you're right, they didn't know how to do it correctly. I don't know anyone who does

☝️ 4

if they’d implemented a state management library you’d be complaining that their solution isn’t composable and isolated


Flux, Redux, MobX, etc. are great experiments that the React team and community has learned a ton from


and we're starting to see the fruit bear in the form of new React APIs that address those concerns, but at the framework-level


“I don’t know anyone who does.” raises-hand


well then show us the way, oh hiskennyness :rolling_on_the_floor_laughing:


They are only making things worse, doubling down on more and more framework in knee jerk solutions to every problem the user community brings to them.


that is the opposite of what they're doing lol


if that had been the case then they would have integrated Flux, or Redux, into React


it's not a knee jerk reaction


@lilactown I understand the skepticism! But I have been at this for 22 years so I am comfortable with the raised hand. See how far you get with this:


@lilactown did you miss this? You asked me to produce it and said I was full of shit, so I think that means you have to read the whole thing and do the exercise on frame 6 and blog about what you learned. 🤞


react has been around for 5 years. they’ve cleared 10,000 bugs! definitely not “knee-jerk”


facebook has ~50,000 react components in their own internal codebase. these guys are not shooting from the hip


Redux was a failure. MobX — imperfections acknowledged! — has been eating its lunch with its transparency. Transparency being a buzzword for “we work out the dataflow, you just write the natural expression of your semantics”.


@hiskennyness I'm not questioning your experience. But I fundamentally think that anyone who claims they have the solution to designing and creating UI applications is full of shit

👆 8

I’m not questioning your language skill, but I think you just questioned my experience. :rolling_on_the_floor_laughing:


I don't think we'll have a great solution in our lifetime


For a second, @lee.justin.m, I thought you were describing CICS. 🙂


I've talked with Jordan Walke and other people who are involved in React / ReasonML and they are all incredibly intelligent, and humble enough to admit that they don't know a lot of answers. some of the questions we don't even know yet


I will take that as a compliment, @lilactown


I don't think there is a ‘the’ solution, everything has benefits and drawbacks


At the end of the day something is good enough to build what I want to build


And I'll learn from using it and move forward after that

👏 4

Just look at the results. They are flailing. And yet they persist. Do you know what it looks like when smart engineers are not expereinced enough to realize they have done bad work?


I mean, I don't think Facebook is 'failing' to serve applications to their users


See “StoneHenge”. Or Ivan Sutherland doing a CAD system in assembler in 1963 with nothing but a light pen that “read” the 1024x1024 CRT screen. The question is, what was the wasted effort using a deficient UI?


What if there is a “the solution”? Would that be a problem in that it violates our meta-certainty of what is possible? Long before Paris the editor of a beekeepers journal saw the Wright brothers flying around a field outside Daytona. He wrote to the Smithsonian to say OMG! The Smithsonian wrote back to say it was impossible, if anyone could fly like that it would have been in the papers. That only cost them a stamp.


Getting back to Suspense, here is a funny story about how dataflow handles Callback Hell without missing a beat (surprised even me):


CBH isn't even really a thing in native js now with async/await, fwiw.


Has anyone come across reagent not re-rendering when the sort order of a subscribed to sorted-map changes? I am guessing it is doing (= sort-map-asc sort-map-desc) when checking props and that returns true whereas (identical? sort-map-asc sort-map-desc) would return false causing a re-render but I am not 100% sure


Pardon a dumb question, but how does the sort order of a sorted-map change? Do you mean sorted-map-by? But I think your guess is right about = being true will get in the way of reagent detecting the change.


Yeah, an event will change the sort order of the map and the subscription will use sorted-map-by to return the sorted map


Hmm, in a repl I just got

`(= (sorted-map-by < :a 2 :b 3) (sorted-map-by :b 3 :a 2)) => false
Oops, forgot the comparator…


This is better:

`(= (sorted-map-by < :a 2 :b 3) (sorted-map-by > :b 3 :a 2)) => true


@jamesthibaudeau i think your diagnosis is correct: because sorted maps with different comparators are =, reagent will not re-render


Ooops: “For ratoms, identical? is used (on the value inside the ratom) to determine if a new value has changed with regard to an old value.”


“For props, = is used to determine if a new value have changed with regard to an old value.” (from the same link)


Make sure, of course, that you are dereferencing the ratom. The ratom remains identical?



(def sorted-state (reagent/atom (sorted-map-by < [0 "zero" 1 "one"])))

(defn child-component
  (js/console.log "child-component")
  [:div (pr-str s)])

(defn test-component
  (js/console.log "test-component")
  [child-component @sorted-state])

(js/setTimeout (fn []
                 (js/console.log "updating comparator")
                 (reset! sorted-state (sorted-map-by > [0 "zero" 1 "one"])))
updating comparator


if you change the reset to (reset! sorted-state @sorted-state) then the second test-component doesn’t print


sorted-map-by wants its keyvals as &rest args, right?


[comparator & keyvals]


yea, though it is irrelevant 🙂


you get the same results


the only thing that matters is that sorted-map is = with different comparators, and when passing props, reagent performs an = check


when choosing when to notify watchers, it uses identical?


what I think I will do is have my subscription return {:order :asc :data sorted-map-asc} or the corresponding desc version


have reagent check the equality on that map instead of the sorted map itself


you can probably do something with protocols / types such that you have a version of sorted map that has different = semantics but being explicit is probably better


yeah, could do it that way too, thanks for your help guys!


is there a different approach to scroll event handler in reagent? all the other events seem to fire, except this one:

      (fn []
        (.addEventListener js/window "scroll" #(js/console.log "hello")))


if I change that to resize, it works


@lilactown did you miss this? You asked me to produce it and said I was full of shit, so I think that means you have to read the whole thing and do the exercise on frame 6 and blog about what you learned. 🤞