Reagent atom value is stil nil after reset function

388 views Asked by At

I made service endpoint api for getting single object by id and it works as expected. I tested it with Postman and in handler function. I use cljs-ajax library for asynchronous client. I cant change the state of Reagent atom when I get response. Here is the code:

(ns businesspartners.core
  (:require [reagent.core :as r]
            [ajax.core :refer [GET POST]]
            [clojure.string :as string]))

(def business-partner (r/atom nil))

(defn get-partner-by-id [id]
  (GET "/api/get-partner-by-id"
       {:headers {"Accept" "application/transit+json"}
        :params {:id id}
        :handler #(reset! business-partner (:business-partner %))}))

When I tried to access business-partner atom I got nil value for that atom. I can't figure out why because another method is almost the same except it get's list of business partners and works fine.

When I change the get-partner-by-id function:

(defn get-partner-by-id [id]
  (GET "/api/get-partner-by-id"
       {:headers {"Accept" "application/transit+json"}
        :params {:id id}
        :handler (fn [arg]
                   (println :handler-arg arg)
                   (reset! business-partner (:business-partner arg))
                   (println "Business partner from handler: " @business-partner))}))

Output in the browser console:

 :handler-arg {:_id 5e7ad2c84b5c2d44583e8ecd, 
               :address Main Street, 
               :email [email protected], 
               :phone 555888, 
               :name Nen Mit}

Business partner from handler:  nil

So, as you can see, I have my object in handler as desired, but when I try to reset my atom nothing happens. That's the core of the problem I think. Thank you Alan.

1

There are 1 answers

2
Alan Thompson On BEST ANSWER

When in doubt, use debug print statements. Make your handler look like this:

:handler (fn [arg]
           (println :handler-arg arg)
           (reset! business-partner (:business-partner arg)))

You may also want to use clojure.pprint/pprint to pretty-print the output, or also add (type arg) to the output.

You may also want to initialize the atom to a specific value like :bp-default so you can see if the nil you observe is the original one or if it is being reset to nil.


Update

So it is clear the key :business-partner does not exist in the map you are receiveing. This is what you must debug.

Trying to pull a non-existent key out of a map always returns nil. You could also use the 3-arg version of get to make this explicit. Convert

(:business-partner arg)  =>  (get arg :business-partner ::not-found)

and you'll see the keyword ::not-found appear in your atom, verifying what is occurring.

In order to catch these problems early, I nearly always use a simple function grab from the Tupelo library like so:

(:business-partner arg)  =>  (grab :business-partner arg)

The grab function will throw an exception if the expected key is not found. This provides early-warning of problems so you can track them down faster.

Another hint: next time use prn instead of println and it will retain double-quotes on string output like:

"Main Street"