Fork me on GitHub
#re-frame
<
2021-09-22
>
restenb12:09:47

hm. was running app on re-frame v1.1.1, just tried bumping to 1.2.0, and the app stops working. initial load seems broken but no errors. any known issues?

p-himik13:09:19

Just to narrow the problem down, you can try using 1.1.2. Also, pay attention to your Reagent version - it might be important.

Franklin13:09:41

Is there a way to dispatch multiple events from one effect handler rather than doing something like this?

(re-frame/reg-event-fx
  ::upload-media-files
  (fn [{db :db}]
    ;; upload media files one by one
    (mapv #(re-frame/dispatch [::upload-single-media-file %])
          (get-in db [:settings :media-files]))
    (assoc-in db [:settings :uploading-media-files?] true)))

p-himik13:09:29

First of all, do not do this - event handlers must stay free of side effects. Second of all, the code above won't work at all because you return db instead of {:db db}. Finally, nowadays the recommended way is to use the :fx effect for dispatches and whatnot. It's well documented.

Franklin13:09:38

I could add a :dispatch key to the coeffect returned from this effect handler

Franklin13:09:49

but... It'll only dispatch a single event right?

Franklin13:09:00

can I dispatch multiple events?

p-himik13:09:46

Coeffects are the map that an event handler registered with reg-event-fx receives. The map that is returned is an effects map, not coeffects. Yes, :dispatch is only for a single event. As I said, read the documentation for the :fx effect - it will let you do what you want.

Charles Suggs16:09:21

hello 👋 ok I am baffled by this, but the answer is probably rather obvious. Maybe #cljsrn is the place for this question, not sure. Anyhow, we're following the re-frame docs and using :http-xhrio for requesting data from an external API as an effect in an event handler. The API response looks a bit like this (as JSON):

{
    "results": [
        12715,
        12677,
        12566,
        11653,
        12439,
        12507,
        12448,
        12410,
        12121,
        12356
    ],
    "facets": [],
    "pager": {
        "page": 1,
        "per_page": 10,
        "total_rows": 576,
        "total_pages": 58
    },
    "posts": [
        {
            "ID": 12715,
            "title": "title one",
            "city": "New York",
            "state": "NY"
        },
        {...}
    ]
}
I've confirmed the response data looks like this via Postman. We can print out the titles just fine to a screen and with prn, but the city field for example only ever has nil for its value in the cljs app. Any ideas for why this string data is nil in re-frame?

p-himik16:09:38

So only a portion of your request data is changed, no the whole request?

Charles Suggs16:09:28

yeah. Some items are just nil, while others are there.

p-himik16:09:49

Does it happen reliable? I.e. when using Postman the city name is always some string, for all posts, and when using CLJS the city name is nil for specific posts that are always the same?

Charles Suggs16:09:49

always the same, city name is always nil in cljs, but always a string with value in postman. Sometimes the city is an empty string in postman, but since we have control of the API we're requesting data from, I did a test to make sure each city field had a string value and that made no difference.

p-himik16:09:21

And where exactly do you put that prn to inspect the data?

Charles Suggs16:09:44

I've done that both in the request handler and in a screen that would print the data, same result both places.

Charles Suggs16:09:52

example from the screen:

(prn (map (fn [post] (:post_title post)) (get-businesses)))
    (prn (map (fn [post] (:city post)) (get-businesses)))
    (doall (map-indexed (fn [index b]
                          [list-item {:title (:post_title b)
                                      :key index}])

                        (get-businesses)))]

Charles Suggs16:09:18

the event handler that makes the request, which I've done with and without the :api being set

(reg-event-fx
 :search-businesses
 (fn [cofx [_ search]]
   {:http-xhrio {:uri "REDACTED"
                 :method :post
                 :params {:query_args {:post_type "business"}}
                 :format (ajax/json-request-format)
                 :response-format (ajax/json-response-format {:keywords? true})
                 :on-success [:businesses-updated]
                 :on-failure [:wp-api-error]
                 :api (js/XMLHttpRequest.)
                 }}))

p-himik16:09:32

The request event handler doesn't have any data yet, so I assume you mean the response event handler. Oh, hold on. First of all, your data above has "title" but in this code you use :post_title - why the difference? You use (get-business) - are you sure calling it multiple times is OK? What does it do? You use (:city post) - are you sure it's indeed :city and not "city" in that data, or something else? Have you tried logging all the posts and seeing what the values are, along with their keys?

p-himik16:09:01

Also, why do you provide :api explicitly?

Charles Suggs16:09:34

And finally the response event handler:

(reg-event-db
 :businesses-updated
 (fn
   [db [_ response]]
   (assoc db :businesses (:posts (js->clj response)))))
now to your questions....

Charles Suggs16:09:05

yeah, the actual key is :post_title not :title, I was just taking a shortcut in describing above.

Charles Suggs16:09:32

(defn get-businesses []
  (let [businesses @(subscribe [:businesses])] businesses))

Charles Suggs16:09:50

I realize that can be shortened to remove the let

Charles Suggs16:09:40

I am sure it's :city because I'm using :response-format (ajax/json-response-format {:keywords? true}) and I've printed out the keys with (keys post) , and the output looks like...

Charles Suggs16:09:57

an excerpt from the prn output that's looping over all the posts and printing out their keys

Charles Suggs16:09:07

The reason I tried providing :api explicitly was this GH issue: https://github.com/JulianBirch/cljs-ajax/issues/204

p-himik16:09:02

Are you using day8.re-frame.http-fx? Because it explicitly overwrites your :api. :)

p-himik16:09:31

Also, I don't think you need that js->clj there because the JSON response format that you specify already parses the JSON string in the response.

👍 2
Charles Suggs16:09:33

yeah, I realized after trying this, that day8.re-frame.http-fx was probably overwriting that anyway. Yeah, we're using that.

Charles Suggs16:09:54

I've dropped the js->clj but it makes no difference

p-himik16:09:56

Right now I have zero clues. I'm 95% certain that it's not re-frame. My best bet is that your backend serves different data to different clients - maybe by checking the user agent. Things to try: • Check the full response data, before any parsing. You can do that with a custom response format • Log the response on the backend to see if "city" is there for those particular requests from your UI • If that's not possible, use WireShark to intercept the request and see the data

Charles Suggs16:09:36

My suspicions were leaning towards either something in day8.re-frame.http-fx or, like you said, the backend doing different things based on user agent. We have a different API endpoint on the same API that's doing the same thing, but there's no problem with its data. I have logged the data in

(reg-event-db
 :businesses-updated
and city is indeed nil there. Was thinking I'd log it in http-fx to see what's happening there. thanks

lilactown17:09:50

if you have a REPL in the RN app you can try initiating a js/fetch and inspecting that

Charles Suggs13:09:53

Wound up fixing this by writing our own API route to request the data from. It's coming out in exactly the same JSON, but for some reason http-xhrio isn't clobbering the values 🤷

p-himik13:09:18

You still haven't really confirmed that it was http-xhrio though.

Charles Suggs13:09:27

that's fair. I hope to have time after the 1st to dig deeper into what was going on but need to meet a deadline first

👍 1
Drew Verlee19:09:09

Is there a way to identify the handler for a dispatch event key in the case where said key isn't a fully qualified ns keyword?

p-himik19:09:32

By "identify the handler", do you mean just getting the handler function itself or actually navigating to its definition in code?

Drew Verlee19:09:53

navigate to where it is defned in the code/text.

p-himik19:09:18

Then the answer is "it depends on your editor/IDE". Nothing re-frame-specific about that.

👍 1
jkrasnay22:09:13

clojure-lsp supports this. If you “go to definition” on a keyword that’s a Re-frame event, it jumps to the definition. Same for subscriptions.