I love this discussion and Iโd like to chip in into this ClojureScript state management library for React, that could work with vanilla React components.
Is there a way to do this collaboratively? Perhaps a online meetup or a wiki or a slack channel or...
@orestis I'd love that, although I'm not sure at all what we'd be aiming to create exactly. I guess that's the research question? ๐
Yep! For me the research question is vaguely: Can we combine the best of ClojureScript (immutability, data structures, opinions about state and identity) and the best of React (engineering effort, recent shift into User experience, browser support, functional paradigm) while leaving behind the worst of JS (unstable ecosystem, churn, verbosity)?
I think helix/uix etc have made one step: bottom out at plain React components, opens the door to seamless interop. If you understand React, you understand hx/helix.
The next step is -> well, hooks is fine and dandy for small-scale local state, but quite quickly you run into limitations. I agree with the analysis of @dominicm for re-frame. Can we learn or get inspired from other UI frameworks, perhaps outside of React or web land? (e.g. Vue, Ember, Swift UI)
How do you manage global state while staying close to the domain model? re-frame has some point about dispatching domain events and letting the low-level details be hidden (stratified design). Having a bunch of functions that operate on the same data structure can also become unwieldy (how do you organise all that into a coherent chunk?). Where do state machines / state charts come into play?
Iโm keeping stuff like that in my personal notes, hoping to eventually be able to synthesize a document out of them.
Thereโs more: how do we get some safety guarantees? Frontend is notoriously fiddly to test so eliminating a type of errors (typos, schema changes) is a big boost. How do spec/schema/malli play into all this? Can it be done via linters like clj-kondo at static time?
BTW itโs not that one thing will solve all of those -> these are frontend concerns that you have to solve in every application, in my experience. The JS world is also grappling with those issues, and thereโs a lot of solutions in this space.
Would be interested in a teleconference call, I could prepare some of my "research" (that is, stuff I gathered while working) to share how I think it's possible to have everything.
https://github.com/reduxjs/react-redux/issues/1177 this is an educational read in any case
I do think that front-end testing is a bit of an unturned stone in CLJS land
the investment required to create a high quality testing library for the DOM/React is quite high, so I've been researching what JS land is using and have landed on adopting react-testing-library at work
it actually works really well. if you're comfortable with (.findByTestId result "foo")
rather than (find-by-test-id result "foo")
, I would highly recommend it
I've only once bothered to test DOM structure, and we all felt it was pretty pointless testing.
I've seen testing of side effects with reframe, testing that certain dispatches happen when buttons are clicked, etc. I'm not really sure that was useful too. It was prone to breaking when arguments changed.
(I'm willing to be convinced otherwise, I'm just not sure what useful front-end testing looks like)
testing dom structure (e.g. that specific types of elements exist, or that a certain shape of tree is constructed) is pretty useless I agree
I don't think I understood the above :)
but for instance, yesterday I wrote a test to ensure that when an element was hovered over, it would show a tooltip. it was akin to:
(let [result (render ($ stats {:data test-data})
title (.getElementByTestId result "stat-title")]
(rtl/fireEvent.mouseOver title)
(-> (.findByTestId "stat-title-tooltip")
(.then #(t/testing "Stat tooltip appears")
(t/is true)))
(.then #(t/testing "Stat tooltip appears")
(t/is false)))
(.then done)))
then I refactored the tooltip functionality to be a shared component because I needed to use it elsewhere - and the test let me know when I broke my stats component ๐
Curious, how did you break it? I think that's always important in these kinds of conversations ๐
tbh I was pretty in the zone and focusing on the stat component at the time, so the breakages I made were expected. times it failed - other than learning how react-testing-library works - were when I was fiddling with adding the new global dom ref to the page where the tooltip would render, so it wasn't rendering at all.
I definitely spent more time writing the test than it would to just manually check if the hover still showed, but what I believe I gained is the ability to be confident that as I continue to hack on the tooltip in an effort to build other pages, it will continue to work for my stats component ๐
I really like kent c dodds approach to thinking about tests: https://kentcdodds.com/blog/write-tests
his point about not testing implementation details, is what lead to me not putting as much weight into testing things like re-frame event dispatching / etc.: https://kentcdodds.com/blog/testing-implementation-details
I would also say that testing the structure of the DOM is an implementation detail, which is why I tried my best to use test IDs instead of querying for class names or doing a snapshot test
Re state management. https://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout/35415559#35415559 this just seems wonderful. Thunks seem like they solve the reframe issue?
I mean, if you are happy with a Singleton store you could bypass it. But I think non Singleton store would be a goal for me.
One nice thing about events is that they can be generated. Combined with causatum, you can generate sequences of events using state machines to simulate progression through your application.
> As a general architectural principle, we want to keep our own components "unaware" of Redux. They should simply receive data and functions as props, just like any other React component. This ultimately makes it easier to test and reuse your own components. How do we feel about this principle? This is something that has bothered me about reframe. Especially that it's created an ecosystem of re-xxx.
it is the #1 thing I dislike about re-frame atm. re-frame is an abstraction that is difficult to build on top of in an agnostic way
Also makes creating a bunch of reusable components (super important for a design system) hard. Probably doable, of course - but not something trivial or (seemingly) encouraged.