This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-15
Channels
- # adventofcode (80)
- # beginners (94)
- # biff (19)
- # cider (74)
- # clj-kondo (11)
- # cljs-dev (7)
- # clojure (110)
- # clojure-austin (3)
- # clojure-australia (1)
- # clojure-belgium (1)
- # clojure-china (1)
- # clojure-europe (83)
- # clojure-filipino (1)
- # clojure-hk (1)
- # clojure-indonesia (1)
- # clojure-japan (1)
- # clojure-korea (1)
- # clojure-my (1)
- # clojure-nl (1)
- # clojure-norway (4)
- # clojure-sg (1)
- # clojure-taiwan (1)
- # clojure-uk (2)
- # cursive (3)
- # data-science (8)
- # datalevin (8)
- # emacs (18)
- # etaoin (5)
- # graalvm (1)
- # holy-lambda (3)
- # honeysql (1)
- # jackdaw (10)
- # java (10)
- # jobs (3)
- # luminus (9)
- # malli (106)
- # off-topic (88)
- # polylith (8)
- # portal (2)
- # re-frame (50)
- # reagent (11)
- # reitit (74)
- # remote-jobs (1)
- # shadow-cljs (46)
- # tools-deps (26)
- # xtdb (49)
how to dispatch synchronously an effect-handler in tests? I am trying to use it like this:
(reg-event-fx
:event-with-coeffect
(fn [{:keys [db]} _]
{:fx [[:dispatch-sync [:add-todo "Make a lunch"]]
[:dispatch-sync [:set-showing :active]]]}))
...test body...
(let [todos (subscribe [:todos])
showing (subscribe [:showing])]
(dispatch-sync [:event-with-coeffect])
(is (= (count @todos) 1))
(is (= @showing :active)))
but todos
and showing
ratoms dont changehave you looked into using https://github.com/day8/re-frame-test?
yes but I try to use just cljs.test
Because all other my frontend tests (events, subs) work w/o re-frame-test
lib
I thought there is a solution with just using re-frame
oh I think dispatch sync is not allowed inside of the events. so I guess there is no effect with dispatch-sync maybe the problem is with that?
maybe, IDK, thats why I ask it here)
I tried also to use :dispatch
inside of :fx
vector - the same issue
with dispatch it makes sense that it is failing as that is async. So I think you need to use the re-frame-test to make the flow synchronous.
if you dont want to pull in dependency you can just mock the dispatch like they did in the library https://github.com/day8/re-frame-test/blob/master/src/day8/re_frame/test.cljc#L297
but then you will need to figure out the state resets between test runs, so I think using the re-frame-test is easier
also you can use it with clj.test
it’s just a library with macros
I see. Btw, dont you know why many clojure/script libs are not fresh? Like re-frame-test
- last commit was 1 year ago
do all the state updates inline in :db and use :fx only for stuff that is side effects
@U3JH98J4R I dont understand you, can you please rephrase?
its just an abstract example of some event with side-effect that is not only changes db, but also does some side-effect.
but both events inside it change db, yes)
add-todo
adds a todo
set-showing
sets showing filter keyword (like :done)
(defn add-todo
[db todo]
(assoc db :todo todo))
(defn set-showing
[db showing-status]
(assoc db :showing-status :showing-status))
(reg-event-fx
:event-with-coeffect
(fn [{:keys [db]} _]
{:db (-> db
(add-todo ...)
(set-showing ...))]}))
(defn add-todo
[db todo]
(assoc db :todo todo))
(defn set-showing
[db showing-status]
(assoc db :showing-status :showing-status))
(defn event:event-with-coeffect
[{:keys [db]} _]
{:db (-> db
(add-todo ...)
(set-showing ...))]})
(reg-event-fx
:event-with-coeffect
(fn [& args]
(apply event:event-with-coeffect args)))
now - lets say that add-todo wants to specify both a state update and side effects to perform
(defn add-todo
[db todo]
{:db (assoc db :todo todo)
:fx [[:http-xhrio ...]]})
(defn set-showing
[db showing-status]
(assoc db :showing-status :showing-status))
(defn event:event-with-coeffect
[{:keys [db]} _]
(let [{db' :db
fx :fx} (add-todo db ...)]
{:db (-> db'
(set-showing ...))]})
(reg-event-fx
:event-with-coeffect
(fn [& args]
(apply event:event-with-coeffect args)))
@U3JH98J4R thanks a lot, will try tomorrow
Hello all, what it means this error message? re-frame: Subscribe was called outside of a reactive context.
Yeah, or in some :on-click
or a similar JS event handler, or in some effect handler, or at some other place.
I think that warning has a stack trace that should help you navigate to the place where the sub is used.
@U2FRKM4TW so, in this way, is this should be a problem
(defn global-search-input []
[:input {... :value @(rf/subscribe [::subs/global-search-value])})
?and something like this? The subscription inside the reg-event-fx
:fx
dispatch?
(rf/reg-event-fx
::show-select-reason-modal
(fx [{:keys [...]} [_ _]]
{:fx [[:dispatch [::delete-modal ....
(let [reason-id (:id @(rf/subscribe [::archive-subs/selected-reason]))] ...
Not sure what you mean. But if you're asking about why the warning exists, that's because subscriptions are cached and using them outside of the reactive context leaks them in the cache. Maybe there were other issues, I don't really recall.
@U2FRKM4TW I see that the current solution needs reason-id
. How would you get it from re-frame-db then? One solution is to pass it as an argument, but let’s say there is 5 level nesting of reg-event-fx
, what could be the alternatives if any?
Event handlers have access to app-db - it's in their first parameters. As is in the case of reg-event-db
and under the :db
key in the case of reg-event-fx
.
Unless your subs are rather complicated, extracting the value then should be rather straightforward.
https://ericnormand.me/guide/database-structure-in-re-frame#evolving-a-database It’s a bit conflicting with that paragraph. I should be reading from DB with subscriptions
and writing it with events
. Or is it still okay to ask directly from DB on that case? And if this is okay, then is there any good pattern for complicated queries?
Yes, that particular section is about views, although it doesn't state it in an obvious way. It's completely OK to talk to the db from within an event handler - that's exactly what the db is there for, right in the first argument of a handler function. Also, instead of reading someone's very verbose understanding of re-frame, I'd suggest simply reading the official documentation and examples. This way, there's much less chance of misunderstanding.
> is there any good pattern for complicated queries? Depends on what you mean by "complicated queries". If you mean that a sub depends upon some other subs, and maybe even in a dynamic way, and then you want to also get that sub's value in an event handler, then no, unfortunately there's no good pattern for that. One way to achieve that would be to separate all pieces of the sub into smaller functions and then compose those functions separately in subs and in event handlers. Another way would be to use a global interceptor, compute the value in it when relevant inputs change, and cache it in the db. Then both the sub and the event handler can just access that cache.