This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-19
Channels
- # adventofcode (44)
- # announcements (2)
- # aws (9)
- # beginners (166)
- # braveandtrue (16)
- # calva (170)
- # cider (14)
- # cljdoc (9)
- # cljs-dev (4)
- # cljsrn (1)
- # clojars (1)
- # clojure (150)
- # clojure-dev (15)
- # clojure-europe (4)
- # clojure-india (3)
- # clojure-italy (93)
- # clojure-nl (18)
- # clojure-serbia (1)
- # clojure-spec (5)
- # clojure-uk (45)
- # clojurescript (54)
- # cursive (19)
- # data-science (8)
- # datomic (83)
- # emacs (6)
- # events (1)
- # hoplon (3)
- # hyperfiddle (3)
- # jobs (6)
- # jobs-discuss (1)
- # klipse (1)
- # lein-figwheel (6)
- # leiningen (15)
- # lumo (1)
- # nrepl (1)
- # pedestal (15)
- # re-frame (48)
- # reagent (4)
- # reitit (2)
- # remote-jobs (1)
- # rum (2)
- # shadow-cljs (111)
- # spacemacs (10)
- # sql (16)
- # testing (10)
- # tools-deps (5)
I’m a Re-Frame beginner and could use a bit of a hint. I’ve got an application created with Figwheel and ReFrame10x in my environment, so I am able to watch data flow through the application. The application has a grid of clickable cells, a cell changes color when clicked because the app-db contains a map entry reporting the last cell clicked. The view dispatches when a cell is clicked, an even receives the event and updates the app-db. There is a reg-sub function for the section of the app-db that is updated and the cells have a subscription to the keyword of the reg-sub. Using a combination of ReFrame10x and printlin calls, I have determined that data is flowing correctly through most of the application. Mouse click generates event, event-handler updates the app-db and the subscription notes the change (:sub/run). But the subscribed view does not render. The only time the view seems to render is when I make a change that causes FigWheel to re-load, at which point all of the view components update (not just the subscribed cells view). The item being subscribed to is a map within the app-db. Only one element of this map is changed, but the subscription is tied to the map itself. I’m presuming that this is sufficient, as the overall map identity should change when the new map containing the changed map is created (changed in the app-db, in the persistent structures sense). I’ve been reviewing the breakout application from lambdaisland (https://github.com/lambdaisland/breakout) looking for anything I have missed, but have not been able to figure out the root cause. Does this sound like anything that has been observed in the past? If not, what would you suggest for next-steps? (Perhaps cutting it down to a minimal example for posting here?) Thank you!
could you post an example of a view component that does not update when the subscription changes?
the most common beginner mistake is perhaps that you're somehow not returning a view function, though I believe the latest re-frame no longer differentiates between form-1 and form-2 components, which cuts out the main source of early confusion
Say I want to do an interceptor to make a change to the db before the handler runs,. Do I put the change to the db in [:context :effects :db]
or [:contexts :coeffects :db]
I ended up setting the db coeffect in :before
, then copying it from the coeffect to the effect in :after
if the effect wasn't set. Hopefully this isn't too wrong!
@shaken There’s a quirk in React that sometimes causes it to re-render an earlier version of a component that should be changed. The fix is to set the :key
metadata on the component to something that changes when the subscription value changes. So maybe something like this:
(defn cell []
(let [selected?-sub (rf/subscribe [:cells/selected])]
(fn []
(let [selected? @selected-sub]
^{:key (str "cell-" (if selected? "selected" "normal"))}
[:div.cell {:class (if selected? "selected" "")} "Value"]))))
@mateus.pimentel.w target="_blank"
?
@mateus.pimentel.w I have a route server-side returning the same index.html page as /
, and then routing client-side shows the right content for /new-page
i mean, i did not explain well haha, for what i understood, people usually switch views by dispatching an “navigate” event, don’t they?
i was thinking about adding some kind of href too and prevent the link from being followed when the user uses right click, but allowing them to open that link in a new tab
I don't usually use navigate, unless it's triggered from another event. I use pushy
which listens to a.click events.
but i realized that, because of some wizardry i did not understand yet, it looks that my links are not making http requests anymore and they just switch the view without losing the app state
Pushy triggers a navigate event when it receives an a.click for a matching route
i’m using material-ui and i would like to put “hrefs” into ListItems and all sorts of things, do you have some suggestion regarding what to do?
Found https://github.com/manishkumarmdb/re-frame-bidi-pushy-example which looks like a good example
Just to confirm, the only element i can use to switch views is the a
element or there are other ways?
You can fire a navigate event yourself too (e.g. in an on-click), there's nothing necessarily wrong with that. It just isn't the 'default' way i do it for normal links.
<a href=
is semantically best
i get annoyed by using links because they don’t fit everywhere and i have to deal with the css
I'm not familiar with material-ui, so my advice might be inappropriate in your case
i will see what happens if i use the Link
component people are talking about ( i think it is from another library )
You could also trigger another event that does (js/window.open url "_blank")
. A link isn't the only way to open a new tab
It has to be triggered by a trusted event (https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted) e.g. a click or swipe. Even then, Chrome (maybe others?) has started blocking those unless the user explicitly allows popups.
@shaken Is render-cells
also a re-frame component? If so you can try returning [render-cells cells-state]
i.e. inside []
instead of ()
@manutter51 Thank you, I’ll give this a try. ReFrame10X & println shows it is not rendering at all, except for the first click after a save/figwheel reload. (I.E. it is not rendering an on earlier version). Is the “quirk” you describe a bug? Or is there desirable behavior that is not evident to a new user.
@manutter51 How would I tell if it is a re-frame component? Changing to a vector doesn’t change the behavior.
@shaken is there a reason for the indirection? why not have the caller of cells-state
call render-cells
directly, and let render-cells
contain the subscribe?
so far as I understand it, it matters not where the rf/subscribe
call lives, but where the deref
/`@` is.
Wait, I just noticed, you’re never dereferencing the subscription
(unless you’re dereferencing it inside render cells
?)
I am dereferencing in the render-cells. (I actually pulled that into a function for clarity here. The render-cells was an anonymous function previouslt.
Ok. You can ignore my earlier question about whether it’s a re-frame component — if it’s returning the hiccup vector for the html you want to render, it’s a re-frame component.
Just for reference, here is how I would typically build something sorta similar to what I think you’re describing:
(defn cell [c selected?]
[:div.cell {:class (if selected? "selected" "")}
(:value c)])
(defn cells-grid []
(let [cells-sub (rf/subscribe [:grid/cells])
selected-sub (rf/subscribe [:grid/selected-cell])]
(fn []
(let [cells @cells-sub
selected @selected-sub]
(into [:div.cells]
(for [c cells :let [cell-id (:id c)
selected? (= selected cell-id)]]
^{:key (str "cell-" cell-id (if selected? "-sel"))}
[cell c selected?]))))))
assuming each cell looked something like {:id 9 :value "X"}
and that the [:grid/selected-cell]
subscription returned the :id
of the currently-selected cell.
I ended up setting the db coeffect in :before
, then copying it from the coeffect to the effect in :after
if the effect wasn't set. Hopefully this isn't too wrong!
Thank you, everyone. Pulling the deference outside the re-frame component resolved my issue. (The content of render-cells is a re-frame component. Thank you for the definition, @manutter51.)
Hi, anyone has thoughts on how to implement server sent events (SSE) using re-frame?
I was thinking about using subsciptions to external data (https://github.com/Day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md), but it seems it's not recommended
Ok, maybe not very generic also not pure, but something like that seems to work:
(rf/reg-event-fx
:attach-to-events-stream
(fn [_ _]
(let [stream (js/EventSource. events-url)]
(set! (.-onmessage stream) (fn [event]
(let [server-event (read-string event.data)
event-name (keyword (str "on-" (name (:type server-event))))]
(rf/dispatch [event-name (dissoc server-event :type)]))))
(set! (.-onerror stream) (fn [event]
(.close stream)
(js/console.error "SSE connection problem" event)
(js/alert "Problem with events sources stream connection, restarting")
(rf/dispatch [:attach-to-events-stream])))
{})))
(rf/reg-fx :events-stream-add
(fn [event]
(ajax/POST events-url {:body event
:response-format (ajax/raw-response-format)
:handler (fn [e]
(js/console.debug e))
:error-handler (fn [e]
(js/console.error e))})))